亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

PythonI/O進階學習筆記_3.2面向對象編程_python的繼承(多繼承

系統 2037 0

前言:

本篇相關內容分為3篇多態、繼承、封裝,這篇為第二篇 繼承。

本篇內容圍繞 python基礎教程這段:
在面向對象編程中,術語對象大致意味著一系列數據(屬性)以及一套訪問和操作這些數據的方法。使用對象而非全局變量和函數的原因有多個,下面列出了使用對象的最重要的好處。
? 多態:可對不同類型的對象執行相同的操作,而這些操作就像“被施了魔法”一樣能夠正常運行。
? 封裝:對外部隱藏有關對象工作原理的細節。
? 繼承:可基于通用類創建出專用類。
內容較多,這篇為中篇。

Content:

- 繼承

1. 什么是繼承,繼承的作用和常用狀態?

2. python的多繼承、instance和type?

3. python中的super函數

4. python的MRO查找機制來對應多繼承和super

5. python的抽象基類

6. django等大大框架和python源碼中最常用的Mixin模式多繼承實例

?(下篇

- 封裝

1.數據封裝和私有屬性

2. 類變量和實例變量(對象變量)

3. 類屬性和實例屬性得查找順序(MRO)

4. 靜態方法 類方法和對象方法使用以及參數

5. python的接口和自省機制

6. 上下文管理器

?)

?

一 繼承

1.什么是繼承?繼承有哪些作用?常用?

? ? - 繼承的概念? :在OOP程序設計中,當我們定義一個class的時候,可以從某個現有的class繼承,新的class稱為子類(Subclass),而被繼承的class稱為基類、父類或超類(Base class、Super class)。

            
              //INPUT:
              
class
Animals(): def say(self): print ( " say something " ) def eat(self): print ( " eat something " ) class Duck(Animals): def say(self): print ( " gaga " ) class Dog(Animals): def say(self): print ( " wangwang " ) class Miao(Animals): def say(self): print ( " miaomiao " ) for i in [Duck(),Dog(),Miao()]: i.eat()

//OUTPUY:
eat something
eat something
eat something

? ? - 繼承的作用:可以解決代碼重用的問題。

? ? - 比較常用的應該就是在python相關web框架里這種比較比較復雜的框架,和許多第三方庫的類。天知道這些大牛的框架里面默默有效率的幫我們做了多少事- -。天知道我們直接用他們的方法有多方便。

?

2.python多繼承需要注意哪些?用instance和type來判斷python類繼承的關系。

a.多繼承需要注意的地方:

- 類繼承的順序和方法在多繼承類中查找的順序

? ? --.子類繼承父類時,在子類進行屬性調用的順序為:先查找自己的屬性字典,若自己的屬性字典中無該屬性,則會依次按照繼承父類的順序來依次查找父類的屬性字典;

? ? --.子類繼承父類,當父類和子類均有相同的屬性時,子類并不會影響父類的屬性。

總結起來就是: 按繼承的順序來依次查詢屬性,一旦查到則停止;子類和父類的屬性相互獨立,互不影響;子類可以調用父類的屬性,反之不行 ;

b.用instance和type來判斷兩個類的關系

instance和type都是用來判斷參數1是否是參數2類型,區別在于是否會考慮繼承關系。

isinstance:
?
type:
type(b)是:
由上可得,type用于判斷對象,而isinstance判斷是否在繼承鏈里面。
?
3.python的super函數
a.super函數干嘛的?為什么要用super?
實際上是用來調用自己的父類的。
super 是用來解決多重繼承問題的,直接用類名調用父類方法在使用單繼承的時候沒問題,但是如果使用多繼承,會涉及到查找順序(MRO)、重復調用(鉆石繼承)等種種問題。MRO 就是類的方法解析順序表, 其實也就是繼承父類方法時的順序表。
?
b.super的用法
在python2中,super(B,self).__init__()
python3中 super().__init__()
                
                  #
                
                
                  Python3.x 實例:
                
                
                  class
                
                
                   A:
     
                
                
                  def
                
                
                   add(self, x):
         y 
                
                = x+1
         
                
                  print
                
                
                  (y)

                
                
                  class
                
                
                   B(A):
    
                
                
                  def
                
                
                   add(self, x):
        super().add(x)
b 
                
                =
                
                   B()
b.add(
                
                2)  
                
                  #
                
                
                   3
                
                
# Python2.x 實例: # !/usr/bin/python # -*- coding: UTF-8 -*- class A(object): # Python2.x 記得繼承 object def add(self, x): y = x+1 print (y) class B(A): def add(self, x): super(B, self).add(x) b = B() b.add( 2) # 3

?

4.super和多繼承時查找父類的順序 MRO C3算法
a.MRO C3算法

C3線性是用于獲取多重繼承下繼承順序的一種算法。通常,被稱為 方法解析順序 ,即MRO(method resolution order)。

算法的名字“C3”并不是縮寫,而是指該算法的三大重要屬性:

- 前趨圖。作為有向無環圖,找不到任何的循環,通常用前趨圖來理解程序的依賴關系。

- 保持局部的優先次序。

- 單調性。

C3是1996年首次被提出。在python2.3及后續版本中,C3被選定為默認的解析算法。

一個類的C3線性表,是由兩部分進行merge操作得到的,第一部分是是它所有父類的C3線性表(parents' linearizations),第二部分是它所有父類組成的列表(parents list)。后者其實是局部的優先級列表。

在C3被應用之前,廣度優先和深度優先是被應用于解析順序的。

C3算法計算方法:有點類似拓撲排序(有向圖) ? ? ?想深刻了解 C3 還是自己查吧...下面有段簡單的多繼承代碼和其對應的拓撲排序的抽象圖 ( 所用代碼實例和圖片均來應用自別處,文章末尾有鏈接 )

                  
                    class
                  
                  
                     D(object):
    
                  
                  
                    pass
                  
                  
                    class
                  
                  
                     E(object):
    
                  
                  
                    pass
                  
                  
                    class
                  
                  
                     F(object):
    
                  
                  
                    pass
                  
                  
                    class
                  
                  
                     C(D, F):
    
                  
                  
                    pass
                  
                  
                    class
                  
                  
                     B(E, D):
    
                  
                  
                    pass
                  
                  
                    class
                  
                  
                     A(B, C):
    
                  
                  
                    pass
                  
                  
                    if
                  
                  
                    __name__
                  
                   == 
                  
                    '
                  
                  
                    __main__
                  
                  
                    '
                  
                  
                    :
    
                  
                  
                    print
                  
                   A.
                  
                    __mro__
                  
                

得到的輸出結果:

                  (<
                  
                    class
                  
                  
                    '
                  
                  
                    __main__.A
                  
                  
                    '
                  
                  >, <
                  
                    class
                  
                  
                    '
                  
                  
                    __main__.B
                  
                  
                    '
                  
                  >, <
                  
                    class
                  
                  
                    '
                  
                  
                    __main__.E
                  
                  
                    '
                  
                  >, <
                  
                    class
                  
                  
                    '
                  
                  
                    __main__.C
                  
                  
                    '
                  
                  >, <
                  
                    class
                  
                  
                    '
                  
                  
                    __main__.D
                  
                  
                    '
                  
                  >, <
                  
                    class
                  
                  
                    '
                  
                  
                    __main__.F
                  
                  
                    '
                  
                  >, 
                  
                    
                      '
                    
                    
                      object
                    
                    
                      '
                    
                    >)
                  
                
  • 下面就是抽象出來的圖


我們就用拓撲排序來分析,但是這里會碰到同時存在好幾個點都是入度為0 (說人話,就是沒有被別人指向的點),這時按照樹的排序來,即 從左到右,從根到葉 ,這里 A 就是根。

所以具體情況就是:我們先找到了點 A只有它沒有被別人指向,輸出 A ;去掉A及其伸出的兩條線,剩 B 和 C 點同時滿足只指向別人,按照樹的順序從左到右,故先輸出 B ;去掉線剩 E 和 C ,輸出 E ;去線剩 C,輸出 C ;去線剩 D 和 F ,輸出 D ;去線只剩F ,輸出 F ;最后輸出 object ;得到的輸出結果:? A B E C D F object

對比系統打印出的結果,順序是一致的。這樣下次你就可以裝逼地手動計算多繼承時調用類的順序了


以上結論來源鏈接:https://www.jianshu.com/p/6651ed35104c

b.用__init__和超類的super().__init__看子類和父類的構造函數關系。
現在有一個繼承關系,SonBird繼承Bird。但是子類和父類都有自己的構造函數。
              
                class
              
              
                 Bird:
    
              
              
                def
              
              
                __init__
              
              
                (self):
          self.hungry 
              
              =
              
                 True
    
              
              
                def
              
              
                 eat(self):
          
              
              
                if
              
              
                 self.hungry:
               
              
              
                print
              
              
                '
              
              
                Ahahahah
              
              
                '
              
              
                else
              
              
                :
               
              
              
                print
              
              
                '
              
              
                No thanks!
              
              
                '
              
              
                class
              
              
                 SongBird(Bird):
     
              
              
                def
              
              
                __init__
              
              
                (self):
          self.sound 
              
              = 
              
                '
              
              
                Squawk
              
              
                '
              
              
                def
              
              
                 sing(self):
          
              
              
                print
              
              
                 self.song()

sb 
              
              =
              
                 SongBird()
sb.sing()    
              
              
                #
              
              
                 能正常輸出
              
              
sb.eat()     
              
                #
              
              
                 報錯,因為 songgird 中沒有 hungry 特性
              
            

這時候,如果需要繼承父類構造函數里的屬性,其實是可以有兩種方法的。

第一種 - 調用未綁定的超類構造方法(多用于舊版 python 陣營)

              
                class
              
              
                 SongBird(Bird):
     
              
              
                def
              
              
                __init__
              
              
                (self):
          Bird.
              
              
                __init__
              
              
                (self)
          self.sound 
              
              = 
              
                '
              
              
                Squawk
              
              
                '
              
              
                def
              
              
                 sing(self):
          
              
              
                print
              
               self.song()
            

原理 :在調用了一個實例的方法時,該方法的self參數會自動綁定到實例上(稱為綁定方法);如果直接調用類的方法(比如Bird.__init__),那么就沒有實例會被綁定,可以自由提供需要的self參數(未綁定方法)。

第二種 - 使用super函數(只在新式類中有用)

              
                class
              
              
                 SongBird(Bird):
     
              
              
                def
              
              
                __init__
              
              
                (self):
          super(SongBird,self).
              
              
                __init__
              
              
                ()
          self.sound 
              
              = 
              
                '
              
              
                Squawk
              
              
                '
              
              
                def
              
              
                 sing(self):
          
              
              
                print
              
               self.song()
            

原理: 它會查找所有的超類,以及超類的超類,直到找到所需的特性為止。

?
5.python的抽象基類(abc)
a.什么是抽象基類? 抽象基類的特性?
  抽象基類的作用類似于JAVA中的接口。在接口中定義各種方法,然后繼承接口的各種類進行具體方法的實現。抽象基類就是定義各種方法而不做具體實現的類,任何繼承自抽象基類的類必須實現這些方法,否則無法實例化。
抽象基類的特性:
- 無法用來實例化。
?
?
b.為什么要有抽象基類?直接用鴨子類型不就好了?
第一個需求:在某些情況下,我們需要判定某個對象的類型。
第二個需求:我們需要強制某個子類必須實現某些方法
?
c.抽象基類的應用
抽象類是不能(至少是不應該)實例化的類,其職責是定義子類應實現的一組抽象方法。
下面是一個簡單的示例:使用@abstractmethod來將方法標記為抽象的——在子類中必須實現的方法。
              
                from
              
               abc 
              
                import
              
              
                 ABC, abstractmethod 

              
              
                class
              
              
                 Talker(ABC): 
  @abstractmethod 
  
              
              
                def
              
              
                 talk(self): 
  
              
              
                pass
              
            

結果:

              ##抽象基類不能被實例化
              
>>> Talker() Traceback (most recent call last): File " " , line 1, in TypeError: Can ' t instantiate abstract class Talker with abstract methods talk
              
                ##沒有重寫方法的時候,繼承抽象基類的類 本質也是抽象類
                
class
Knigget(Talker): pass ##由于沒有重寫方法talk,因此這個類也是抽象的,不能實例化。如果你試圖這樣做,將出現類似于前面的錯誤消息。
              
                ###繼承后重寫了方法就沒什么問題
                
class
Knigget(Talker): def talk(self): print ( " Ni! " )

##output:
>>> k = Knigget()
>>> isinstance(k, Talker)
True 1
>>> k.talk()
Ni!

?

6.混入模式:多繼承應用實例(Mixin 模式)
首先,Mixin模式在python應用中十分常見,包括openstack、django等,有大量的Mixin模式應用。想要進階,就需要理解為什么大部分框架都會用這種模式。
詳細的谷歌大神關于動態語言的設計模式可以看: http://norvig.com/design-patterns/ppframe.htm?或者《松本行弘的程序世界》里有介紹ruby的混入模式和python一樣。
?
從某種程度上來說,繼承強調 I am,Mixin 強調 I can。
?
以下來自: https://www.liaoxuefeng.com/wiki/897692888725344/923030524000032

在設計類的繼承關系時,通常,主線都是單一繼承下來的,例如, Ostrich 繼承自 Bird 。但是,如果需要“混入”額外的功能,通過多重繼承就可以實現,比如,讓 Ostrich 除了繼承自 Bird 外,再同時繼承 Runnable 。這種設計通常稱之為Mixin。

為了更好地看出繼承關系,我們把 Runnable Flyable 改為 RunnableMixin FlyableMixin 。類似的,你還可以定義出肉食動物 CarnivorousMixin 和植食動物 HerbivoresMixin ,讓某個動物同時擁有好幾個Mixin:

          
            
              
                class 
                
                  Dog
                  
                    (Mammal, RunnableMixin, CarnivorousMixin):
    
                    
                      pass 
                    
                  
                
              
            
          
        

Mixin的目的就是給一個類增加多個功能,這樣,在設計類的時候,我們優先考慮通過多重繼承來組合多個Mixin的功能,而不是設計多層次的復雜的繼承關系。

Python自帶的很多庫也使用了Mixin。舉個例子,Python自帶了 TCPServer UDPServer 這兩類網絡服務,而要同時服務多個用戶就必須使用多進程或多線程模型,這兩種模型由 ForkingMixin ThreadingMixin 提供。通過組合,我們就可以創造出合適的服務來。

比如,編寫一個多進程模式的TCP服務,定義如下:

          
            
              
                class 
                
                  MyTCPServer
                  
                    (TCPServer, ForkingMixin):
    
                    
                      pass 
                    
                  
                
              
            
          
        

編寫一個多線程模式的UDP服務,定義如下:

          
            
              
                class 
                
                  MyUDPServer
                  
                    (UDPServer, ThreadingMixin):
    
                    
                      pass 
                    
                  
                
              
            
          
        

如果你打算搞一個更先進的協程模型,可以編寫一個 CoroutineMixin

          
            
              
                class 
                
                  MyTCPServer
                  
                    (TCPServer, CoroutineMixin):
    
                    
                      pass 
                    
                  
                
              
            
          
        

這樣一來,我們不需要復雜而龐大的繼承鏈,只要選擇組合不同的類的功能,就可以快速構造出所需的子類。

?


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦?。。?/p>

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 欧美色成人tv在线播放 | 伊人久久大香线蕉亚洲 | 日本在线 | 中文 | 欧美激情视频二区三区 | 久久综合久久久 | 奇米精品 | 狠狠色先锋资源网 | 亚洲欧美另类久久久精品能播放的 | 天天夜天天干 | 欧美一区二区三 | 天天舔天天插 | 看免费黄色一级视频 | 91久久青草精品38国产 | 成人亚洲在线观看 | 婷婷色基地 | 四虎在线最新永久免费播放 | 91手机在线视频 | 国产福利小视频在线观看 | 亚洲午夜久久久久中文字幕久 | 日韩视频免费一区二区三区 | 精品国产日韩一区三区 | 四虎影视免费永久在线观看 | 狠狠色噜噜狠狠狠狠色综合网 | 亚洲欧美日韩图片 | 午夜国产精品色福利视频 | 一级特黄性色生活片一区二区 | 色综七七久久成人影 | 欧美亚洲国产精品 | 国产一区二区影院 | 国产成人教育视频在线观看 | 视频一区国产精戏刘婷 | 精品国产免费一区二区三区 | 亚洲a免费 | 亚洲国产成人久久一区久久 | 波多野结衣久久 | 一级毛片成人免费看免费不卡 | www中文字幕| 久久我们这里只有精品国产4 | www.色日本| 久久久久久88色愉愉 | 亚洲精品免费在线视频 |