最近在學習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