r={'a':6}
c = Myclass(**r)
out: a
当我执行Myclass(**r)
时,该类从fields
而不是MyMeta
被称为Myclass
。在这个过程中会发生什么?为什么不使用fields
中的Myclass
?
class MyMeta(type) :
def __new__(mcs,name,bases,attr) :
fields = {}
fields['a'] = 2
fields['b'] = 4
fields['c'] = 44
if '__init__' not in attr:
def init(self,**kwargs):
self.api = kwargs.pop('api', None)
for k,v in kwargs.items():
if k in fields :
print(v)
attr['__init__'] = init
return type.__new__(mcs,name,bases,attr)
class Myclass(metaclass = MyMeta ):
fields = {'c': 5}
def get(self):
print(4)
答案 0 :(得分:2)
目前尚不清楚为什么需要在这里使用元类,您可能不需要。但是为了进行练习,让我们检查一下正在进行的事情。
Python函数的作用域定义如下
locals > closure > globals > builtins
永远不会在调用它的作用域的命名空间中进行函数查找。请注意,在这种情况下,即使定义MyClass.__init__
也行不通,因为类方法必须通过属性访问其类名称空间。
class SomeClass:
foo = 0
def __init__(self):
self.foo # works
foo # raises NameError
特别是,这意味着您的init
方法将在fields
的主体(即其闭包)中找到MyMeta.__new__
。
不过,请注意,类的名称空间作为第四个参数传递给MyMeta.__new__
方法,此处为attr
。因此,您可以在Myclass.fields
的{{1}}处找到attr['fields']
。
MyMeta.__new__
class MyMeta(type):
def __new__(mcs, name, bases, attr):
fields = {'foo': 0}
def init(self, **kwargs):
print('kwargs:', kwargs)
print('MyMeta.__new__.fields:', fields)
print('attr["fields"]:', attr['fields'])
attr['__init__'] = init
return type.__new__(mcs, name, bases, attr)
class Myclass(metaclass=MyMeta):
fields = {'bar': 1}
r = {'baz': 2}
c = Myclass(**r)