调用类__init__时,为什么类从其元类访问变量?

前端之家收集整理的这篇文章主要介绍了调用类__init__时,为什么类从其元类访问变量? 前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

r={'a':6} 
c = Myclass(**r) 
out: a 

当我执行Myclass(** r)时,此类从MyMeta而不是Myclass调用字段.在这个过程中会发生什么?为什么不使用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,attr)

class Myclass(Metaclass = MyMeta ):
    fields = {'c': 5} 
    def get(self):
        print(4) 
最佳答案
目前尚不清楚为什么在这里需要一个元类,您可能不需要.但是,为了进行练习,让我们检查一下正在进行的事情.

Python函数的范围是这样定义的

locals > closure > globals > builtins

永远不会在调用范围的名称空间中查找函数.请注意,在这种情况下,即使定义MyClass .__ init__也不起作用,因为类方法必须通过属性访问其类名称空间.

class SomeClass:
    foo = 0
    def __init__(self):
        self.foo # works
        foo # raises NameError

特别是,这意味着您的init方法将在MyMeta .__ new__的主体中找到字段,这是它的闭包.

虽然,请注意,将类的名称空间作为第四个参数传递给MyMeta .__ new__方法(此处为attr).因此,您可以在MyMeta .__ new__的attr [‘fields’]上找到Myclass.fields.

class MyMeta(type):
    def __new__(mcs,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,attr)


class Myclass(Metaclass=MyMeta):
    fields = {'bar': 1}


r = {'baz': 2}
c = Myclass(**r)

输出

kwargs: {'baz': 2}
MyMeta.__new__.fields: {'foo': 0}
attr["fields"]: {'bar': 1}
原文链接:https://www.f2er.com/python/533247.html

猜你在找的Python相关文章