加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

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

发布时间:2020-12-17 17:40:16 所属栏目:Python 来源:网络整理
导读: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

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}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读