gpt4 book ai didi

python:元类中__new__的时间

转载 作者:太空狗 更新时间:2023-10-30 03:07:41 24 4
gpt4 key购买 nike

以下代码无法编译;它说

NameError: name 'fields' is not defined

在最后一行。是因为 __new__ 直到达到 fields 赋值后才被调用吗?我该怎么办?

class Meta(type):
def __new__(mcs, name, bases, attr):
attr['fields'] = {}
return type.__new__(mcs, name, bases, attr)

class A(metaclass = Meta):
def __init__(self, name):
pass

class B(A):
fields['key'] = 'value'

编辑:

我发现这不是时间问题;这是名字隐藏的问题。如果我改写 A.fields 就可以正常工作。

我想知道为什么我不能使用 fieldssuper().fields

最佳答案

fields['key'] = 'value'在元类机制启动之前运行。

class foo(object):
var1 = 'bar'

def foobar(self):
pass

当 python 命中 class 时语句,它进入一个新的本地命名空间。

  1. 它评估 var1 = 'bar'陈述。这相当于 locals()['var1'] = 'bar'

  2. 然后计算 def foobar陈述。这相当于 locals()['var'] = the result of compiling the function

  3. 然后通过locals() ,连同类名、继承的类和元类的元类 __new__方法。在示例中,元类只是 type .

  4. 然后退出新的本地命名空间并粘贴从 __new__ 返回的类对象在名称为 foo 的外部命名空间中.

当您使用 A.fields 时,您的代码有效因为类 A已经创建,因此上面的过程已经用你的 Meta 执行了安装 fieldsA .

您不能使用 super().fields因为类名 B未定义为在 super 运行时传递给 super。那就是你需要它是 super(B).fields但是B在类创建之后定义。

更新

根据您对我对问题的评论的回复,这里有一些代码可以执行您想要的操作。

def MakeFields(**fields):
return fields

class Meta(type):
def __new__(mcs, name, bases, attr):
for base in bases:
if hasattr(base, 'fields'):
inherited = getattr(base, 'fields')
try:
attr['fields'].update(inherited)
except KeyError:
attr['fields'] = inherited
except ValueError:
pass
return type.__new__(mcs, name, bases, attr)

class A(metaclass=Meta):
fields = MakeFields(id='int',name='varchar')

class B(A):
fields = MakeFields(count='int')

class C(B):
pass

class Test(object):
fields = "asd"

class D(C, Test):
pass

print C.fields
print D.fields

关于python:元类中__new__的时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3723979/

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