【问题标题】:Metaclass not being called in subclasses子类中未调用元类
【发布时间】:2010-12-18 17:57:19
【问题描述】:

这是一个 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__ 被调用,并打印两行,这没有发生,(因为 metaclass 是继承的?)

【问题讨论】:

    标签: python metaclass


    【解决方案1】:

    问题在于调用type时没有传递cls参数(即元类对象),因此创建并返回的类对象Y没有对元类的任何引用Z.

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

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

    然后就可以了。请注意,即使在 super 中使用了 cls,我们仍然必须提供 cls 作为参数,因为这里的 super 返回一个未绑定的方法(请参阅 here 了解更多信息)。

    作为使用 super one 的替代方法,可以使用:

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

    重要的是我们将cls(我们的元类对象Z)赋予类方法__new__。较短的形式type(name, bases, attrs)cls 参数填充type 本身,这当然是错误的。此错误类似于使用错误的self 参数调用实例方法。

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

    【讨论】:

    • 啊,好吧,那行。但是return super(Z, cls).__new__不应该等同于type.__class__.new,而应该等同于type.__new__,这应该与通过type创建一个新类相同?
    • 实际上不一样,我现在在回答中解决这个问题。 Super 确实调用了type.__new__ 方法,但是我们可以使用正确的cls 参数,如果我们直接调用type,这是不可能的。
    猜你喜欢
    • 2012-11-03
    • 1970-01-01
    • 2012-08-19
    • 1970-01-01
    • 2012-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-14
    相关资源
    最近更新 更多