博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
为什么类会拥有其元类的属性?
阅读量:4977 次
发布时间:2019-06-12

本文共 1383 字,大约阅读时间需要 4 分钟。

最近在学习Python的一些设计模式,当看到用元类实现单例模式代码的时候,发现一个很有意思的问题,先看代码:

class Meta(type):    _instances = {}    def __call__(cls, *args, **kwargs):        if cls not in cls._instances:            cls._instances[cls] = type.__call__(cls, *args, **kwargs)        return cls._instances[cls]

问题是_instances不是元类的属性吗?为什么可以通过cls._instances来访问?

stackoverflow有人曾提过相同的问题,。

编写了一些实验的代码,如下:

class TopMeta(type):    topmeta = 'topmeta'class MetaBaseCls:    metabasecls = 'metabasecls'    class UpperMeta(type, MetaBaseCls, metaclass=TopMeta):    uppermeta = 'uppermeta'    attr = 'uppermeta attr'class BaseCls:    basecls='basecls'    attr = 'basecls attr'class C(BaseCls, metaclass=UpperMeta):    passC.baseclsC.uppermetaC.metabaseclsC.attrtry:    print(C.topmeta)except Exception as e:    print(e)

输出为:

'basecls''uppermeta''metabasecls''basecls attr'type object 'C' has no attribute 'topmeta'

根据上面的实验,可以发现:

  1. C会先在自身的继承链里查找,所以打印basecls attr,而不是uppermeta attr。
  2. uppermeta和metabasecls都在其元类的继承链中,所以都可以找到。
  3. topmeta是其元类的元类,并不在其元类的继承链中,找不到,会报错。

具体的实现细节没有完全弄清楚,但简单总结一些规律:

对象(注意这个对象包含实例和类)会先在自己的整个继承链里面寻找属性,如果没有找到,则会在它的类的继承链里面寻找属性,而类是元类的实例,换句话说,类的类是元类。所以类会先在自身的继承链里面查找属性,如果找不到,则到它的元类的继承链里面查找属性。

这里容易想不通的是按照以上解释,实例的继承链不就是其类的继承链吗?那不是重复了?

个人是这样理解,实例是通过object类创造出来,类是通过type类创造出来,所以本质上说实例和类是不同的东西,类有继承链,实例没有,只有自身的命名空间。所以对于实例来说,先在自己的命名空间里面查找属性,找不到,再在其类的继承链里寻找属性。
如果有不对的地方,请大家指出。

转载于:https://www.cnblogs.com/telecomshy/p/9297086.html

你可能感兴趣的文章
编译预处理指令:文件包含指令、宏定义指令、条件编译指令
查看>>
PHP函数 ------ ctype_alnum
查看>>
网站安全
查看>>
WS-Addressing 初探
查看>>
.NET+模块编排+数据库操作类的封装+分层架构+实体类+Ajax.net+Athem.NET+javascript+Activex组件+用户权限等...
查看>>
Markdown不常见功能
查看>>
(二)NUnit单元测试心得
查看>>
hdu_2604Queuing(快速幂矩阵)
查看>>
frame.bounds和center
查看>>
HDU 1102 Constructing Roads
查看>>
android StaticLayout参数解释
查看>>
多线程之ThreadLocal类
查看>>
Qt-读取文本导出word
查看>>
OC语言description方法和sel
查看>>
C#中得到程序当前工作目录和执行目录的五种方法
查看>>
扫描线与悬线
查看>>
用队列和链表的方式解决约瑟夫问题
查看>>
python 迭代器与生成器
查看>>
基于ASP.NET WEB API实现分布式数据访问中间层(提供对数据库的CRUD)
查看>>
[django实践]投票app
查看>>