1. 程式人生 > >Python進階-----元類及自定製元類

Python進階-----元類及自定製元類

一、什麼是元類
  元類:就是生成類的的類,或者說是類的模版。

 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 = age
12 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'}