元类未在子类中调用

发布于 2024-08-11 21:56:10 字数 518 浏览 4 评论 0原文

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

Here is a python session.

>>> 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
>>> 

After I define class X I expect Z._new__ to be called for it, and to print the two line, which is not happening, (as metaclass are inherited?)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

耀眼的星火 2024-08-18 21:56:10

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

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

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

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

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

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

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

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

The problem is that the cls argument (which is the metaclass object) is not passed on when you call type, therefore the class object Y that is created and returned does not have any reference to the metaclass Z.

If you replace the last line in __new__ with

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

then it works. Note that even though cls is used in super we still have to provide cls as an argument as well, since super here returns an unbound method (see here for more).

As an alternative to using super one could use:

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

The important thing is that we give cls (our metaclass object Z) to the classmethod __new__. The shorter form type(name, bases, attrs) fills in type itself for the cls argument, which is of course wrong. This error is similar to calling an instance method with the wrong self argument.

I prefer using super, since this is better style.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文