未在子类中调用元类

agi*_*liq 10 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
>>> 
Run Code Online (Sandbox Code Playgroud)

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

nik*_*kow 13

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

如果更换的最后一行__new__

return super(Z, cls).__new__(cls, name, bases, attrs)
Run Code Online (Sandbox Code Playgroud)

然后它工作.请注意,即使cls是用在super我们还是要提供cls作为参数为好,因为super这里返回未绑定的方法(参见这里更多).

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

 return type.__new__(cls, name, bases, attrs)
Run Code Online (Sandbox Code Playgroud)

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

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

  • 啊,好的,那个工作.但是不应该返回super(Z,cls).__ new__`等同于`type .__ class __.new` whis相当于`type .__ new__`,它应该与通过`type`创建一个新类相同? (2认同)
  • 它实际上是不一样的,我现在在我的回答中解决这个问题.Super确实调用`type .__ new__`方法,但我们可以使用正确的`cls`参数,如果我们直接调用`type`则这是不可能的. (2认同)