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

Python中super()函數(shù)簡介及用法分享

系統(tǒng) 1857 0

首先看一下super()函數(shù)的定義:

super([type [,object-or-type]])

Return a **proxy object** that delegates method calls to a **parent or sibling** class of type.

返回一個代理對象, 這個對象負責將方法調用分配給第一個參數(shù)的一個父類或者同輩的類去完成.

parent or sibling class 如何確定?

第一個參數(shù)的__mro__屬性決定了搜索的順序, super指的的是 MRO(Method Resolution Order) 中的下一個類, 而不一定是父類!

super()和getattr() 都使用__mro__屬性來解析搜索順序, __mro__實際上是一個只讀的元組.

MRO中類的順序是怎么排的呢?

實際上MRO列表本身是根據(jù)一種C3的線性化處理技術確定的, 理論說明可以參考這里, 這里只簡單說明一下原則:

在MRO中, 基類永遠出現(xiàn)在派生類的后面, 如果有多個基類, 基類的相對順序不變.

MRO實際上是對繼承樹做層序遍歷的結果, 把一棵帶有結構的樹變成了一個線性的表, 所以沿著這個列表一直往上, 就可以無重復的遍歷完整棵樹, 也就解決了多繼承中的Diamond問題.

比如說:

            
class Root:
  pass

class A(Root):
  pass

class B(Root):
  pass

class C(A, B):
  pass

print(C.__mro__)

# 輸出結果為:
# (
            
              , 
              
                , 
                
                  , 
                  
                    , 
                    
                      )


                    
                  
                
              
            
          

super()實際返回的是一個代理的super對象!

調用super()這個構造方法時, 只是返回一個super()對象, 并不做其他的操作.

然后對這個super對象進行方法調用時, 發(fā)生的事情如下:

找到第一個參數(shù)的__mro__列表中的下一個直接定義了該方法的類, 并實例化出一個對象
然后將這個對象的self變量綁定到第二個參數(shù)上, 返回這個對象

舉個例子:

            
class Root:
  def __init__(self):
    print('Root')

class A(Root):
  def __init__(self):
    super().__init__() # 等同于super(A, self).__init__()


          

在A的構造方法中, 先調用super()得到一個super對象, 然后向這個對象調用init方法, 這是super對象會搜索A的__mro__列表, 找到第一個定義了__init__方法的類, 于是就找到了Root, 然后調用Root.__init__(self), 這里的self是super()的第二個參數(shù), 是編譯器自動填充的, 也就是A的__init__的第一個參數(shù), 這樣就完成對__init__方法調用的分配.

注意: 在許多語言的繼承中, 子類必須調用父類的構造方法, 就是為了保證子類的對象能夠填充上父類的屬性! 而不是初始化一個父類對象...(我之前就一直是這么理解的..). Python中就好多了, 所謂的調用父類構造方法, 就是明明白白地把self傳給父類的構造方法, 我的小身子骨就這么交給你了, 隨便你怎么折騰吧:joy:

參數(shù)說明

            
super() -> same as super(__class__, 
            
              ) # 
              
                指的是調用super的函數(shù)的第一個參數(shù)
super(type) -> unbound super object
super(type, obj) -> bound super object; requires isinstance(obj, type)
super(type, type2) -> bound super object; requires issubclass(type2, type)

 Typical use to call a cooperative superclass method:
  class C(B):
    def meth(self, arg):
      super().meth(arg)
  This works for class methods too:
  class C(B):
    @classmethod
    def cmeth(cls, arg):
      super().cmeth(arg)


              
            
          

如果提供了第二個參數(shù), 則找到的父類對象的self就綁定到這個參數(shù)上, 后面調用這個對象的方法時, 可以自動地隱式傳遞self.
如果第二個參數(shù)是一個對象, 則isinstance(obj, type)必須為True. 如果第二個參數(shù)為一個類型, 則issubclass(type2, type)必須為True

如果沒有傳遞第二個參數(shù), 那么返回的對象就是Unbound, 調用這個unbound對象的方法時需要手動傳遞第一個參數(shù), 類似于Base.__int__(self, a, b).

不帶參數(shù)的super()只能用在類定義中(因為依賴于caller的第二個參數(shù)), 編譯器會自動根據(jù)當前定義的類填充參數(shù).
也就是說, 后面所有調用super返回對象的方法時, 第一個參數(shù)self都是super()的第二個參數(shù). 因為Python中所謂的方法, 就是一個第一個參數(shù)為self的函數(shù), 一般在調用方法的時候a.b()會隱式的將a賦給b()的第一個參數(shù).

super()的兩種常見用法:

單繼承中, super用來指代隱式指代父類, 避免直接使用父類的名字
多繼承中, 解決Diamond問題 (TODO)

對面向對象的理解

其實我覺得Python里面這樣的語法更容易理解面向對象的本質, 比Java中隱式地傳this更容易理解.

所謂函數(shù), 就是一段代碼, 接受輸入, 返回輸出. 所謂方法, 就是一個函數(shù)有了一個隱式傳遞的參數(shù). 所以方法就是一段代碼, 是類的所有實例共享的, 唯一不同的是各個實例調用的時候傳給方法的this 或者self不一樣而已.

構造方法是什么呢? 其實也是一個實例方法啊, 它只有在對象生成了之后才能調用, 所以Python中__init__方法的參數(shù)是self啊. 調用構造方法時其實已經(jīng)為對象分配了內存, 構造方法只是起到初始化的作用, 也就是為這段內存里面賦點初值而已.

Java中所謂的靜態(tài)變量其實也就是類的變量, 其實也就是為類也分配了內存, 里面存了這些變量, 所以Python中的類對象我覺得是很合理的, 也比Java要直觀. 至于靜態(tài)方法, 那就與對象一點關系都沒有了, 本質就是個獨立的函數(shù), 只不過寫在了類里面而已. 而Python中的classmethod其實也是一種靜態(tài)方法, 不過它會依賴于cls對象, 這個cls就是類對象, 但是只要想用這個方法, 類對象必然是存在的, 不像實例對象一樣需要手動的實例化, 所以classmethod也可以看做是一種靜態(tài)變量. 而staticmethod就是真正的靜態(tài)方法了, 是獨立的函數(shù), 不依賴任何對象.

Java中的實例方法是必須依賴于對象存在的, 因為要隱式的傳輸this, 如果對象不存在這個this也沒法隱式了. 所以在靜態(tài)方法中是沒有this指針的, 也就沒法調用實例方法. 而Python中的實例方法是可以通過類名來調用的, 只不過因為這時候self沒辦法隱式傳遞, 所以必須得顯式地傳遞.


更多文章、技術交流、商務合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

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

【本文對您有幫助就好】

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

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 中文字幕视频免费在线观看 | 欧美片欧美日韩国产综合片 | 欧美另类videosbestv | 天堂一区二区三区精品 | 日本一级在线观看视频播放 | 级毛片| 亚洲图片 欧美 | 噜噜色图 | 国产成人亚洲综合a∨婷婷 国产成人亚洲综合欧美一部 | 羞羞视频在线观看 | 色综合久久最新中文字幕 | 成人爽a毛片在线视频网站 成人爽视频 | 天天搞天天操 | 大伊香蕉精品视频在线天堂 | 欧美精品成人a多人在线观看 | 蜜桃久久久久久久久久久 | 日韩国产欧美成人一区二区影院 | 欧美性视频在线 | www夜夜操| 一本久久a久久精品亚洲 | 久久久久欧美精品 | 亚洲欧美精品综合中文字幕 | 国产精品久久久久久免费播放 | 日本一区毛片免费观看 | 国产福利视频一区二区三区 | 国产高清久久99 | 亚洲毛片视频 | 91在线短视频 | 香蕉视频网站在线观看 | 亚洲视频精品在线 | 奇米影视888狠狠狠777九色 | 夜色伊人 | 久久99热久久精品 | 97精品免费视频 | 国产在线综合网 | 日韩欧美亚洲 | 青青青青手机在线视频观看国产 | www.奇米第四色 | 激情婷婷综合 | 国产成人精品曰本亚洲77美色 | 亚洲国产成人精品一区91 |