gpt4 book ai didi

python - 为什么我不能更改类的 __metaclass__ 属性?

转载 作者:太空狗 更新时间:2023-10-30 00:00:16 25 4
gpt4 key购买 nike

我有一个关于元类的奇怪和不寻常的用例,我想在基类被定义后更改 __metaclass__,以便它的子类将自动使用新的 __metaclass__ 。但这奇怪地不起作用:

class MetaBase(type):
def __new__(cls, name, bases, attrs):
attrs["y"] = attrs["x"] + 1
return type.__new__(cls, name, bases, attrs)

class Foo(object):
__metaclass__ = MetaBase
x = 5

print (Foo.x, Foo.y) # prints (5, 6) as expected

class MetaSub(MetaBase):
def __new__(cls, name, bases, attrs):
attrs["x"] = 11
return MetaBase.__new__(cls, name, bases, attrs)

Foo.__metaclass__ = MetaSub

class Bar(Foo):
pass

print(Bar.x, Bar.y) # prints (5, 6) instead of (11, 12)

我正在做的事情很可能是不明智的/不受支持的/未定义的,但我终其一生都无法弄清楚旧的元类是如何被调用的,我想至少了解这是怎么可能的。

编辑: 根据 jsbueno 的建议,我将 Foo.__metaclass__ = MetaSub 行替换为以下行,这确实正是我想要的:

Foo = type.__new__(MetaSub, "Foo", Foo.__bases__, dict(Foo.__dict__))

最佳答案

问题是继承时未使用 __metaclass__ 属性,这与您的预期相反。也不会为 Bar 调用“旧”元类。文档说明了如何找到元类:

The appropriate metaclass is determined by the following precedence rules:

  • If dict['__metaclass__'] exists, it is used.
  • Otherwise, if there is at least one base class, its metaclass is used (this looks for a __class__ attribute first and if not found, uses its type).
  • Otherwise, if a global variable named __metaclass__ exists, it is used.
  • Otherwise, the old-style, classic metaclass (types.ClassType) is used.

所以在您的 Bar 类中实际用作元类的是在父级的 __class__ 属性中找到的,而不是在父级的 __metaclass__ 属性中。

更多信息可以在 this StackOverflow answer 上找到.

关于python - 为什么我不能更改类的 __metaclass__ 属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8867029/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com