我应该使用元类,类装饰器还是覆盖__new__方法?

时间:2010-03-23 21:15:29

标签: python inheritance metaclass

这是我的问题。我希望以下类具有一堆属性属性。我可以像foobar一样写出来,或者基于我见过的其他一些例子,看起来我可以使用类装饰器,元类或覆盖{{1方法自动设置属性。我只是不确定“正确”的做法是什么。

__new__

3 个答案:

答案 0 :(得分:5)

魔术很糟糕。它使您的代码更难理解和维护。您几乎不需要元类或__new__

看起来你的用例可以用相当简单的代码实现(只有一点点魔力):

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

    def __getattr__(self, name):
        return self.calculate_attr(name)

答案 1 :(得分:2)

元类的__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

这有助于您更好地理解 的元类吗?

很少需要定义自己的元类。

答案 2 :(得分:1)

创建新类 - 而非实例 - 时使用元类。这样你就可以注册类(django会这样做,并使用它来例如在数据库中创建表)。由于class是一个指令,你可以将其视为一个类的装饰器。