未在子类中调用元类

时间:2009-11-20 14:18:55

标签: python metaclass

这是一个python会话。

>>> class Z(type):
    def __new__(cls, name, bases, attrs):
        print cls
        print name
        return type(name, bases, attrs)
...     
>>> class Y(object):
    __metaclass__ = Z
...     
<class '__main__.Z'>
Y
>>> class X(Y):
...     pass
... 
>>> class W(Y):
...     __metaclass__ = Z
...     
<class '__main__.Z'>
W
>>> 

在我定义了类X后,我希望为它调用Z._new__,并打印两行,这是没有发生的(因为元类是继承的吗?)

1 个答案:

答案 0 :(得分:13)

问题是当你调用cls时没有传递type参数(它是元类对象),因此创建和返回的类对象Y不会有任何对元类Z的引用。

如果您将__new__中的最后一行替换为

return super(Z, cls).__new__(cls, name, bases, attrs)

然后它的工作原理。请注意,即使在cls中使用super,我们仍然必须提供cls作为参数,因为此处super会返回未绑定的方法(请参阅here为了更多)。

作为使用超级的替代方案,可以使用:

 return type.__new__(cls, name, bases, attrs)

重要的是我们将cls(我们的元类对象Z)提供给classmethod __new__type(name, bases, attrs)缩写形式type填充了cls参数,这当然是错误的。此错误类似于使用错误的self参数调用实例方法。

我更喜欢使用super,因为这是更好的风格。