1即碗、metaclass有兩個(gè)個(gè)作用域 類中、模塊中對(duì)應(yīng)的在本地類作用和在當(dāng)前模塊中所有的類中作用
同時(shí)metacalss的查找順序是 當(dāng)前類中陌凳、父類中拜姿、當(dāng)前模塊中查找metaclass。
2冯遂、查找到metaclass后蕊肥、首先使用type創(chuàng)建類對(duì)象、之后使用__call__函數(shù)創(chuàng)建類對(duì)象的實(shí)例對(duì)象。
3壁却、創(chuàng)建類對(duì)象的時(shí)候始終使用 type類型的類對(duì)象.__new__函數(shù)創(chuàng)建類對(duì)象批狱、之后調(diào)用 type類型的類對(duì)象.__init__函數(shù)初始化類對(duì)象、但是最終創(chuàng)建類對(duì)象的是type.__new__的元類函數(shù)創(chuàng)建類對(duì)象展东。其中__new__的參數(shù)包括(元類類型cls赔硫,類名,父類元組()盐肃,類的屬性字典)爪膊。
4、當(dāng)我們使用剛創(chuàng)建的類對(duì)象實(shí)例化時(shí) Foo()時(shí) 調(diào)用時(shí)最終使用的是type.__call__函數(shù)創(chuàng)建的實(shí)例對(duì)象砸王,中間可能會(huì)使用自己定義在元類類型中的__call__函數(shù)來執(zhí)行一些動(dòng)作推盛,但最終還是由type.__call__來創(chuàng)建、type元類直接和c語言對(duì)接【猜測(cè)】
5谦铃、我們可以通過修改繼承type元類的元類類型中的 __new__ 耘成、 __init__、 __call__私用方法來操作類對(duì)象的創(chuàng)建驹闰、類對(duì)象對(duì)應(yīng)的實(shí)例對(duì)象瘪菌。
6、所有的__new__函數(shù)必須有返回值嘹朗、__init__函數(shù)不能有返回值貨值返回值是None师妙。
這是使用type.__call__時(shí)的運(yùn)行代碼、自動(dòng)調(diào)用類對(duì)象的__new__屹培、__init__函數(shù)
import pprintas pp
name='wang'
class meta1(type):
? def __new__(cls, *args, **kwargs):
? ? ? pp.pprint('自己創(chuàng)建元類')
? ? ? return type.__new__(cls, *args, **kwargs)
? def __init__(self,class_name,class_bases,class_attr):
? ? ? # self.name1是類對(duì)象屬性
? ? ? self.name1='zhong'
? ? ? pp.pprint('下面3行是類名默穴、父類、類對(duì)象的屬性')
? ? ? pp.pprint(class_name)
? ? ? pp.pprint(class_bases)
? ? ? pp.pprint(class_attr)
? #? 這里的call會(huì)攔截類中定義的__new__惫谤、__init__對(duì)象
? def __call__(self, *args, **kwargs):
? ? ? pp.pprint('call')
? ? ? # self.name1是類對(duì)象屬性
? ? ? pp.pprint(self.name1)
? ? ? pp.pprint(id(self))
? ? ? # 執(zhí)行type.__call__(self, *args, **kwargs)時(shí)候 會(huì)自動(dòng)調(diào)用類對(duì)象中的__new__壁顶、__init__函數(shù)
? ? ? obj=type.__call__(self, *args, **kwargs)
? ? ? # obj=object.__new__(self)
# obj=self.__new__(self,*args, **kwargs)
# pp.pprint('++++++++')
# self.__init__(self,*args, **kwargs)
? ? ? pp.pprint(id(obj))
? ? ? return obj
pp.pprint('yyyyyyyyyyyy')
class t1(object,metaclass=meta1):
? def f1(self):
? ? ? pp.pprint('lei de chuang jian ')
? def __new__(cls, *args, **kwargs):
? ? ? print('class? ? ***8')
? ? ? return object.__new__(cls)
? def __init__(self,name):
? ? ? self.name12='jjjj'
? ? ? print('classinit')
pp.pprint('uuuuuuuuuuuuuuuuuu')
if __name__=='__main__':
? pp.pprint('88888')
? # pp.pprint(dir(t1))
? pp.pprint(id(t1))
? ff=t1('cheng')
? pp.pprint(ff.name12)
? pp.pprint(id(ff))
? # ff是類的實(shí)例化對(duì)象,不是類對(duì)象所以沒有name1屬性溜歪。
? # pp.pprint(ff.name1)
這是輸出結(jié)果:
'yyyyyyyyyyyy'
'自己創(chuàng)建元類'
'下面3行是類名若专、父類、類對(duì)象的屬性'
't1'
(<class 'object'>,)
{'__init__': <function t1.__init__ at 0xb77c292c>,
'__module__': '__main__',
'__new__': <function t1.__new__ at 0xb77c28e4>,
'__qualname__': 't1',
'f1': <function t1.f1 at 0xb77c289c>}
'uuuuuuuuuuuuuuuuuu'
'88888'
3078373884
'call'
'zhong'
3078373884
class? ? ***8
classinit
3079005772
'jjjj'
3079005772
參考的文章如下