gpt4 book ai didi

python - 重写 __new__ 的基元类生成带有错误 __module__ 的类

转载 作者:太空宇宙 更新时间:2023-11-03 19:16:25 25 4
gpt4 key购买 nike

我发现 cpython 2.5、2.7、3.2 和 pypy 的奇怪行为,其元类覆盖 __new__当使用 python 2/python 3 兼容的元类使用方式时:

给定一个模块 m1:

class C1Meta(type):
def __new__(cls, name, bases, dct):
return type.__new__(cls, name, bases, dct)

C1 = C1Meta('C1', (object,), {})


class C2Meta(type):
pass

C2 = C2Meta('C2', (object,), {})

以及以下主程序:

import m1

C10 = m1.C1Meta('C10', (m1.C1,), {})


class C11Meta(m1.C1Meta):
pass

C11 = C11Meta('C11', (m1.C1,), {})


class C12Meta(m1.C1Meta):
def __new__(cls, name, bases, dct):
return m1.C1Meta.__new__(cls, name, bases, dct)

C12 = C12Meta('C12', (m1.C1,), {})


class C13Meta(m1.C1Meta):
def __new__(cls, name, bases, dct):
return type.__new__(cls, name, bases, dct)

C13 = C13Meta('C13', (m1.C1,), {})


C20 = m1.C2Meta('C20', (m1.C2,), {})


class C21Meta(m1.C2Meta):
pass

C21 = C21Meta('C21', (m1.C2,), {})


class C22Meta(m1.C2Meta):
def __new__(cls, name, bases, dct):
return m1.C2Meta.__new__(cls, name, bases, dct)

C22 = C22Meta('C22', (m1.C2,), {})


class C23Meta(m1.C2Meta):
def __new__(cls, name, bases, dct):
return type.__new__(cls, name, bases, dct)

C23 = C23Meta('C23', (m1.C2,), {})


print(C10)
print(C11)
print(C12)
print(C13)

print(C20)
print(C21)
print(C22)
print(C23)

运行脚本将产生以下输出(包含所有提到的 python 版本):

<class 'm1.C10'>
<class 'm1.C11'>
<class 'm1.C12'>
<class '__main__.C13'>
<class '__main__.C20'>
<class '__main__.C21'>
<class '__main__.C22'>
<class '__main__.C23'>

-> C10、C11 和 C12 类模块错误!

这是预期的行为吗?

有没有办法覆盖new而不会引发问题?

谢谢

克里斯托夫

最佳答案

显然是 __module__属性在元类执行时设置。在您的情况下,元类在 m1 内执行。对于正常定义的类,__module__属性会自动生成并传递给元类。但是,您通过手动调用元类来创建类,并传入一个属性字典。因此,您的类(class)不提供 __module__属性。 __module__属性会自动创建,但直到 type.__new__叫做。由于这发生在模块 m1 内部,__module__当时创建的是指m1 .

我不太确定为什么要显式调用元类。元类的全部意义在于允许您自定义使用 class 时会发生的情况。定义类的语句。如果您不想使用 class语句,您可以只使用常规函数来创建类,而根本不需要费心使用元类。

也就是说,我相信您可以通过执行以下操作来获得所需的行为:

C11 = C11Meta('C11', (m1.C1,), {'__module__': __name__})

关于python - 重写 __new__ 的基元类生成带有错误 __module__ 的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11209521/

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