最近在学习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): pass C.basecls C.uppermeta C.metabasecls C.attr try: print(C.topmeta) except Exception as e: print(e)
输出为:code
'basecls' 'uppermeta' 'metabasecls' 'basecls attr' type object 'C' has no attribute 'topmeta'
根据上面的实验,能够发现:对象
具体的实现细节没有彻底弄清楚,但简单总结一些规律:
对象(注意这个对象包含实例和类)会先在本身的整个继承链里面寻找属性,若是没有找到,则会在它的类的继承链里面寻找属性,而类是元类的实例,换句话说,类的类是元类。因此类会先在自身的继承链里面查找属性,若是找不到,则到它的元类的继承链里面查找属性。继承
这里容易想不通的是按照以上解释,实例的继承链不就是其类的继承链吗?那不是重复了?
我的是这样理解,实例是经过object类创造出来,类是经过type类创造出来,因此本质上说实例和类是不一样的东西,类有继承链,实例没有,只有自身的命名空间。因此对于实例来讲,先在本身的命名空间里面查找属性,找不到,再在其类的继承链里寻找属性。
若是有不对的地方,请你们指出。get