1. 程式人生 > >面向物件【day08】:類的起源與metaclass(二)

面向物件【day08】:類的起源與metaclass(二)

本節內容

1、概述

2、類的起源

3、__new__方法

4、__metaclass__方法

一、概述

   前面我們學習了大篇幅的關於類,通過類建立物件,那我們想知道這個類到底是怎麼產生的呢?它的一切來源是什麼?還有物件,物件是通過什麼方法建立的,現在我們一頭霧水,行的,下面我們就來揭開類的面紗,看看類和物件到底是怎麼建立的,通過什麼建立的。

二、類的起源

2.1 傳統建立類

1 2 3 4 5 class  Foo( object ):      def  __init__( self ,name):         
self .name  =  name   =  Foo( "shuaigaogao" )

f 是通過 Foo 類例項化的物件,其實,不僅 f 是一個物件,Foo類本身也是一個物件,因為在Python中一切事物都是物件,

按照一切事物都是物件的理論:obj物件是通過執行Foo類的構造方法建立,那麼Foo類物件應該也是通過執行某個類的 構造方法 建立。

1 2 print ( type (f))     #輸出:<class '__main__.Foo'>  表示:f 物件由Foo類建立 print ( type (Foo))   #輸出:<class 'type'>          表示:Foo類物件由 type 類建立

所以,f物件是Foo類的一個例項Foo類物件是 type 類的一個例項,即:Foo類物件 是通過type類的構造方法建立 

2.2 type建立類

說明:  type建立類的格式,類名 = type('類名',(父類,),{'方法名':方法的記憶體地址})

1 2 3 4 5 6 7 8 9 10 11 12 13 def  func( self ):   #建立方法      print ( "hello {0}" . format ( self .name))   def  __init__( self ,name):   #建立構造方法      self .name  =  name   #通過type建立類,如果是經典類的話則寫成:Foo = type("Foo",(),{"talk":func,"__init__":__init__}) Foo  =  type ( "Foo" ,( object ,),{ "talk" :func, "__init__" :__init__})  =  Foo( "shuaigaogao" )   #建立物件 f.talk()   #輸出 hello shuaigaogao

總結:類 是由 type 類 例項化產生的

值得注意的是,新式類的寫法,在繼承父類那邊,你繼承一個父類後面就要加一個逗號,加逗號,它就把它當做一個元組,不加逗號,就是一個值了

三、__new__方法

3.1 概念

new方法是類自帶的一個方法,可以重構,__new__方法在例項化的時候也會執行,並且先於__init__方法之前執行

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class  Foo( object ):        def  __init__( self ,name):          self .name  =  name            print ( "Foo __init__" )        def  __new__( cls * args,  * * kwargs):          print ( "Foo __new__" , cls * args,  * * kwargs)          return  object .__new__( cls )   =  Foo( "shuaigaogao" )   #輸出 Foo __new__ < class  '__main__.Foo' > shuaigaogao   #執行了new方法 Foo __init__   #執行了__init__方法

3.2 new方法作用

作用:所有物件都是通過new方法來例項化的,new裡面呼叫了init方法,所以在例項化的過程中先執行的是new方法,而不是init方法。

①重構__new__方法

1 2 3 4 5 6 7 8 9 10 11 12 13 class  Foo( object ):        def  __init__( self ,name):          self .name  =  name          print ( "Foo __init__" )        def  __new__( cls * args,  * * kwargs):          print ( "Foo __new__" , cls * args,  * * kwargs)   =  Foo( "shuaigaogao" )   #例項化   #輸出 Foo __new__ < class  '__main__.Foo' > shuaigaogao

由上面的例子看出,沒有執行__init__方法

②重構__new__方法,並繼承父類的__new__方法

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class  Foo( object ):        def  __init__( self ,name):          self .name  =  name            print ( "Foo __init__" )        def  __new__( cls * args,  * * kwargs):    #cls相當於傳入類Foo          print ( "Foo __new__" , cls * args,  * * kwargs)          return  object .__new__( cls )   #繼承父類的__new__方法,這邊必須以返回值的形式繼承   =  Foo( "shuaigaogao" )   #輸出 Foo __new__ < class  '__main__.Foo' > shuaigaogao Foo __init__

由上面不難看出,大多數情況下,你都不要去重構你的__new__方法,因為你父類中已經有__new__方法了,已經幫你寫好了怎麼去建立類,如果你重寫的話,就會覆蓋父類的裡面的__new__方法。但是你重構可以增加一點小功能,但是你覆蓋了以後還是需要繼承父類回來,要不然你的這個實力就建立不了。

3.3 使用場景

我想對我自己寫的一些類進行定製,就在它例項化之前就進行定製,就可以用到__new__方法,new方法就是用來建立實力的,重構new方法,必須以返回值的形式繼承父類的new方法。

①需求:我在建立物件時候,同時建立一個類變數

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class  Foo( object ):        def  __init__( self ,name):          self .name  =  name            print ( "Foo __init__" )        def  __new__( cls * args,  * * kwargs):   #cls相當於是傳入的類名Foo          cls .name  =  "shuaigaogao"   #建立物件是定義靜態變數          print ( cls .name)          return  object .__new__( cls )   #繼承父類的__new__方法   =  Foo( "shuaigaogao" ) print (Foo.name)   #輸出 shuaigaogao Foo __init__ shuaigaogao

四、__metaclass__方法

4.1 metaclass作用

metaclass這個屬性叫做元類,它是用來表示這個類是由誰來幫他例項化建立的,說白了,就是相當於自己定製一個類,就這麼一個意思。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class  MyType( type ):      def  __init__( self , * args, * * kwargs):            print ( "Mytype __init__" , * args, * * kwargs)        def  __call__( self * args,  * * kwargs):          print ( "Mytype __call__" * args,  * * kwargs)          obj  =  self .__new__( self )          print ( "obj " ,obj, * args,  * * kwargs)          print ( self )          self .__init__(obj, * args,  * * kwargs)          return  obj        def  __new__( cls * args,  * * kwargs):          print ( "Mytype __new__" , * args, * * kwargs)          return  type .__new__( cls * args,  * * kwargs)   class  Foo( object ,metaclass = MyType):   #python3統一用這種      #__metaclass__ = MyType  #python2.7中的寫法        def  __init__( self ,name):          self .name  =  name            print ( "Foo __init__" )        def  __new__( cls * args,  * * kwargs):          print ( "Foo __new__" , cls * args,  * * kwargs)          return  object .__new__( cls )   =  Foo( "shuaigaogao" ) print ( "f" ,f) print ( "fname" ,f.name)   #輸出 Mytype __new__ Foo (< class  'object' >,) { '__new__' : <function Foo.__new__ at  0x0000025EF0EFD6A8 >, '__init__' : <function Foo.__init__ at  0x0000025EF0EFD620 >,  '__qualname__' 'Foo' '__module__' '__main__' } Mytype __init__ Foo (< class  'object' >,) { '__new__' : <function Foo.__new__ at  0x0000025EF0EFD6A8 >,   '__init__' : <function Foo.__init__ at  0x0000025EF0EFD620 >,  '__qualname__' 'Foo' '__module__' '__main__' } Mytype __call__ shuaigaogao Foo __new__ < class  '__main__.Foo' > obj  <__main__.Foo  object  at  0x0000025EF0F05048 > shuaigaogao < class  '__main__.Foo' > Foo __init__ f <__main__.Foo  object  at  0x0000025EF0F05048 > fname shuaigaogao

建立過程如下:

4.2 執行順序

類的生成 呼叫 順序依次是 __new__ --> __init__ --> __call__

metaclass 詳解文章:猛擊這裡 得票最高那個答案寫的非常好

作者:羅阿紅 出處:http://www.cnblogs.com/luoahong/ 本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連線。

本節內容

1、概述

2、類的起源

3、__new__方法

4、__metaclass__方法

一、概述

   前面我們學習了大篇幅的關於類,通過類建立物件,那我們想知道這個類到底是怎麼產生的呢?它的一切來源是什麼?還有物件,物件是通過什麼方法建立的,現在我們一頭霧水,行的,下面我們就來揭開類的面紗,看看類和物件到底是怎麼建立的,通過什麼建立的。

二、類的起源

2.1 傳統建立類

1 2 3 4 5 class  Foo( object ):      def  __init__( self ,name):          self .name  =  name   =  Foo( "shuaigaogao" )

f 是通過 Foo 類例項化的物件,其實,不僅 f 是一個物件,Foo類本身也是一個物件,因為在Python中一切事物都是物件,按照一切事物都是物件的理論:obj物件是通過執行Foo類的構造方法建立,那麼Foo類物件應該也是通過執行某個類的 構造方法 建立。

1 2 print ( type (f))     #輸出:<class '__main__.Foo'>  表示:f 物件由Foo類建立 print ( type (Foo))   #輸出:<class 'type'>          表示:Foo類物件由 type 類建立

所以,f物件是Foo類的一個例項Foo類物件是 type 類的一個例項,即:Foo類物件 是通過type類的構造方法建立 

2.2 type建立類

說明:  type建立類的格式,類名 = type('類名',(父類,),{'方法名':方法的記憶體地址})

1 2 3 4 5 6 7 8 9 10 11 12 13 def  func( self ):   #建立方法      print ( "hello {0}" . format ( self .name))   def  __init__( self ,name):   #建立構造方法      self .name  =  name   #通過type建立類,如果是經典類的話則寫成:Foo = type("Foo",(),{"talk":func,"__init__":__init__}) Foo  =  type ( "Foo" ,( objec