Я должен использовать метакласс, декоратора класса, или переопределить __ новый __ метод?

Вот моя проблема. Я хочу, чтобы следующий класс имел набор атрибутов свойства. Я мог или записать им всем как 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')
6
задан 23 March 2010 в 22:16
поделиться

3 ответа

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

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

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

    def __getattr__(self, name):
        return self.calculate_attr(name)
5
ответ дан 16 December 2019 в 21:37
поделиться

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

1
ответ дан 16 December 2019 в 21:37
поделиться

Метакласс __ 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 с переопределением new. Различия между этой функцией незначительны.)

Она выводит

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

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

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

2
ответ дан 16 December 2019 в 21:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: