Python進階-----元類及自定製元類
阿新 • • 發佈:2018-11-04
一、什麼是元類
元類:就是生成類的的類,或者說是類的模版。
1 #定義一個類來看一下 2 class Meanwey: 3 pass 4 m = Meanwey() 5 6 #通過type來檢視物件的類 7 print(type(m)) #<class '__main__.Meanwey'> m這個物件是屬於Meanwey這個類 8 9 #類本身也是物件,所以可以用type來檢視 10 print(type(Meanwey)) #<class 'type'> Meanwey這個類物件屬於type這個類
通過上述簡單程式碼可以看到,預設元類就是type。
二、所以可以用type這個元類來生成類
語法:想要生成的類名 = type(想要生成的類名,(繼承的類預設objec,),屬性字典{'x':1})。
注意:type中有三個引數,第一個引數是想要生成的類名為字串型別;第二個引數是繼承的類預設為obje為元組型別;第三個引數為生成的類的屬性字典為字典型別。
1 Meanwey = type('Meanwey',(object,),{'name':'Meanwey'}) 2 m1 = Meanwey() 3 print(type(m1)) #<class '__main__.Meanwey'> 4 print(type(Meanwey)) #<class 'type'> 5 6 # 可以看到通過type來生成的類和class關鍵字生成的類一樣 7 # 當然也可以給類新增函式(方法)屬性,則需要在type語句前先定義好函式(方法),然後在type的第三個引數添中加上函式屬性和函式名 8 9 def __init__(self,name,age): #新增建構函式 10 self.name = name 11 self.age = age12 def test(self): 13 print('呼叫了test方法') 14 15 Meanwey = type('Meanwey',(object,),{'name':'Meanwey','__init__':__init__,'test':test}) #加上函式屬性 16 m1 = Meanwey('小明同學',24) #因為上面定義了建構函式__init__需要name,age兩個引數,所以在例項化的時候需要傳入 17 # print(type(m1)) #<class '__main__.Meanwey'> 18 # print(type(Meanwey)) #<class 'type'> 19 20 #檢視初始化建構函式是否成功 21 print(m1.__dict__) #{'name': '小明同學', 'age': 24} 22 23 #呼叫test函式 24 m1.test() #呼叫了test方法
三、自定製元類
一個類沒有宣告自己的元類,預設他的元類就是type,除了使用內建元類type,我們也可以通過繼承type來自定義元類,然後使用metaclass關鍵字引數為一個類指定元類。
1 #自定義元類 2 class Meta_Type(type): 3 def __call__(self,*args,**kwargs): 4 5 #self是Meta_Type的例項,也就是Foo 6 #因為每個類都預設繼承object,所以可以呼叫__new__(Foo)方法,來例項化一個物件f1 == object.__new__(Foo) ==> f1 7 obj = object.__new__(self) 8 9 #呼叫Foo的建構函式例項化物件 == Foo.__init__(f1,*args,**kwargs) 10 self.__init__(obj,*args,**kwargs) 11 12 #最後要返回f1這個物件 13 return obj 14 15 #metaclass = Meta_Type ====> 會觸發Foo = Meta_Type(Foo,'Foo',(),{}) ===>會觸發Meta_Type的 __init__ 16 class Foo(metaclass=Meta_Type): 17 def __init__(self,name): 18 self.name = name 19 20 #當Foo()時,表示執行了Foo,則會呼叫元類的__call__,__call__中會生成物件f1,並且呼叫Foo下的__init__方法,最終完成例項化 21 f1 = Foo('Menawey') 22 23 #>>>我是元類 24 25 print(f1.__dict__) 26 #>>>{'name': 'Menawey'}