Себичен питон

Метакласовете в Python са много яко нещо. Макар все още да не ми се е наложило да напиша дори един такъв за работата си, са много полезен източник на забавления. Сега ще ви покажа как с малко остроумие може да дефинирате класове по следния интересен начин:

class Person(object):
    __metaclass__ = selfless
    def __init__(name, age):
        self.name = name
        self.age = age

    def __repr__():
        return "Person(%s, %d)" % (repr(self.name), self.age)

    def sayHi():
        print "Hello, I’m %s and I’m %d years old" % (self.name, self.age)

    def rename(newName):
        self.name = newName

Интересното? Въобще не ви се налага да пишете self пред имената на методите.

Как го постигам? Доста просто:

from types import FunctionType

class selfless(type):
    def __new__(cls, name, bases, classDict):
        for attr in classDict:
            if not isinstance(classDict[attr], FunctionType): continue
            classDict[attr] = selflessWrapper(classDict[attr])
        return type.__new__(cls, name, bases, classDict)


def selflessWrapper(func):
    def wrapper(self, *args, **kwargs):
        hadSelf, oldSelf = func.func_globals.has_key(‘self’), \
                func.func_globals.get(‘self’)
        func.func_globals[‘self’] = self
        returnValue = func(*args, **kwargs)
        if hadSelf:
            func.func_globals[‘self’] = oldSelf
        else:
            del func.func_globals[‘self’]
        return returnValue
    wrapper.func_name = func.func_name + "_wrapper"
    return wrapper

В общи линии, създавам нов метаклас, който барва всички функции на инстанциите си. Разширява ги с по един аргумент, а в глобалната им област на видимост добавя едно ново име (self), което след това възстановява. В резултат, всяка функция вижда self, а самия клас вижда функциите като такива с един аргумент повече. Едва ли е нужно да казвам, че цялата врътка става във selflessWrapper.

Вашият коментар

Вашият имейл адрес няма да бъде публикуван. Задължителните полета са отбелязани с *