Должен ли я использовать метакласс, декоратор класса или переопределить метод __new__? - PullRequest
6 голосов
/ 24 марта 2010

Вот моя проблема. Я хочу, чтобы следующий класс имел несколько атрибутов свойств. Я мог бы либо выписать их все как foo и bar, либо, основываясь на некоторых других примерах, которые я видел, похоже, что я мог бы использовать декоратор класса, метакласс или переопределить метод __new__ для установки свойства автоматически. Я просто не уверен, каким будет «правильный» способ сделать это.

class Test(object):
    def calculate_attr(self, attr):
        # do calculaty stuff
        return attr

    @property
    def foo(self):
        return self.calculate_attr('foo')

    @property
    def bar(self):
        return self.calculate_attr('bar')

Ответы [ 3 ]

5 голосов
/ 24 марта 2010

Магия это плохо. Это усложняет понимание и поддержку вашего кода. Вам практически никогда не нужны метаклассы или __new__.

Похоже, ваш вариант использования может быть реализован с довольно простым кодом (с небольшим намеком на магию):

class Test(object):
    def calculate_attr(self, attr):
        return something

    def __getattr__(self, name):
        return self.calculate_attr(name)
2 голосов
/ 24 марта 2010

Метакласс __new__ не становится __new__ для создаваемого вами класса - он используется для создания самого класса. Фактический объект класса возвращается метаклассом. Новый экземпляр класса возвращается __new__.

Рассмотрим следующий (безумный) код:

def MyMetaClass(name, bases, dict):
    print "name", name
    print "bases", bases
    print "dict", dict
    return 7

class C('hello', 'world'):
    __metaclass__ = MyMetaClass

    foo = "bar"

    def baz(self, qux):
        pass

print "C", C

(Я использовал функцию вместо класса в качестве метакласса. Любой вызываемый объект можно использовать в качестве метакласса, но многие люди выбирают свои классы, которые наследуют от type с новым переопределением. функция тонкая.)

выводит

name C
bases ('hello', 'world')
dict {'baz': <function baz at 0x4034c844>, '__module__': '__main__', 'foo': 'bar', '__metaclass__': <function MyMetaClass at 0x40345c34>}
C 7

Помогает ли это вам лучше понять, какие метаклассы ?

Вам очень редко потребуется определить собственный метакласс.

1 голос
/ 24 марта 2010

Метакласс используется при создании нового класса, а не экземпляра. Таким образом, вы можете, например, зарегистрировать классы (django делает это и использует его, например, для создания таблиц в базе данных). Поскольку class - это инструкция, которую вы можете рассматривать как декоратор для класса.

...