最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python中super函數(shù)用法實(shí)例分析

 更新時(shí)間:2019年03月18日 10:57:48   作者:gohom  
這篇文章主要介紹了Python中super函數(shù)用法,結(jié)合實(shí)例形式詳細(xì)分析了Python中super函數(shù)的功能、調(diào)用父類相關(guān)原理、操作技巧與注意事項(xiàng),需要的朋友可以參考下

本文實(shí)例講述了Python中super函數(shù)用法。分享給大家供大家參考,具體如下:

這是個(gè)高大上的函數(shù),在python裝13手冊(cè)里面介紹過多使用可顯得自己是高手 23333. 但其實(shí)他還是很重要的. 簡單說, super函數(shù)是調(diào)用下一個(gè)父類(超類)并返回該父類實(shí)例的方法. 這里的下一個(gè)的概念參考后面的MRO表介紹.

help介紹如下:

super(type, obj) -> bound super object; requires isinstance(obj, type)
super(type) -> unbound super object
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(C, self).meth(arg)

由此可知, super有三種用法, 第一參數(shù)總是召喚父類的那個(gè)類, 第二參數(shù)可缺(返回非綁定父類對(duì)象),也可以是實(shí)例對(duì)象或該類的子類. 最終返回的都是父類的實(shí)例(綁定或非綁定). 在Python3中,super函數(shù)多了一種用法是直接super(),相當(dāng)于super(type,首參), 這個(gè)首參就是一般的傳入的self實(shí)例本身啦. 因?yàn)樵趐y2里面常用也是這種寫法.

另外, 在py2中, super只支持新類( new-style class, 就是繼承自object的).

為什么要調(diào)用父類?

在類繼承時(shí), 要是重定義某個(gè)方法, 這個(gè)方法就會(huì)覆蓋掉父類的相應(yīng)同名方法. 通過調(diào)用父類實(shí)例, 可以在子類中同時(shí)實(shí)現(xiàn)父類的功能.例如:

# Should be new-class based on object in python2.
class A(object):
 def __init__(self):
  print "enter A"
  print "leave A"
class B(A):
 def __init__(self):
  print "enter B"
  super(B, self).__init__()
  print "leave B"
>>> b = B()
enter B
enter A
leave A
leave B

通過調(diào)用super獲得父類實(shí)例從而可以實(shí)現(xiàn)該實(shí)例的初始化函數(shù). 這在實(shí)踐中太常用了 (因?yàn)橐^承父類的功能, 又要有新的功能).

直接使用父類來調(diào)用的差異

事實(shí)上, 上面的super函數(shù)方法還可以這么寫:

class A(object):
 def __init__(self):
  print "enter A"
  print "leave A"
class B(A):
 def __init__(self):
  print "enter B"
  A.__init__(self)
  print "leave B"

通過直接使用父類類名來調(diào)用父類的方法, 實(shí)際也是可行的. 起碼在上面的例子中效果上他們現(xiàn)在是一樣的. 這種方法在老式類中也是唯一的調(diào)用父類的方法 (老式類沒有super).

通過父類類名調(diào)用方法很常用, 比較直觀. 但其效果和super還是有差異的. 例如:

class A(object):
 def __init__(self):
  print "enter A"
  print "leave A"
class B(A):
 def __init__(self):
  print "enter B"
  A.__init__(self)
  print "leave B"
class C(A):
 def __init__(self):
  print "enter C"
  A.__init__(self)
  print "leave C"
class D(B,C):
 def __init__(self):
  print "enter D"
  B.__init__(self)
  C.__init__(self)
  print "leave D"
>>> d=D()
enter D
enter B
enter A
leave A
leave B
enter C
enter A
leave A
leave C
leave D

可以發(fā)現(xiàn), 這里面A的初始化函數(shù)被執(zhí)行了兩次. 因?yàn)槲覀兺瑫r(shí)要實(shí)現(xiàn)B和C的初始化函數(shù), 所以分開調(diào)用兩次, 這是必然的結(jié)果.

但如果改寫成super呢?

class A(object):
 def __init__(self):
  print "enter A"
  print "leave A"
class B(A):
 def __init__(self):
  print "enter B"
  super(B,self).__init__()
  print "leave B"
class C(A):
 def __init__(self):
  print "enter C"
  super(C,self).__init__()
  print "leave C"
class D(B,C):
 def __init__(self):
  print "enter D"
  super(D,self).__init__()
  print "leave D"
>>> d=D()
enter D
enter B
enter C
enter A
leave A
leave C
leave B
leave D

會(huì)發(fā)現(xiàn)所有父類ABC只執(zhí)行了一次, 并不像之前那樣執(zhí)行了兩次A的初始化.

然后, 又發(fā)現(xiàn)一個(gè)很奇怪的: 父類的執(zhí)行是 BCA 的順序并且是全進(jìn)入后再統(tǒng)一出去. 這是MRO表問題, 后面繼續(xù)討論.

如果沒有多繼承, super其實(shí)和通過父類來調(diào)用方法差不多. 但, super還有個(gè)好處: 當(dāng)B繼承自A, 寫成了A.__init__, 如果根據(jù)需要進(jìn)行重構(gòu)全部要改成繼承自 E,那么全部都得改一次! 這樣很麻煩而且容易出錯(cuò)! 而使用super()就不用一個(gè)一個(gè)改了(只需類定義中改一改就好了)

Anyway, 可以發(fā)現(xiàn), super并不是那么簡單.

MRO 表

MRO是什么? 可以通過以下方式調(diào)出來:

>>> D.mro() # or d.__class__.mro() or D.__class__.mro(D) 
[D, B, C, A, object]
>>> B.mro()
[B, A, object]
>>> help(D.mro)
#Docstring:
#mro() -> list
#return a type's method resolution order
#Type:  method_descriptor

MRO就是類的方法解析順序表, 其實(shí)也就是繼承父類方法時(shí)的順序表 (類繼承順序表去理解也行) 啦.

這個(gè)表有啥用? 首先了解實(shí)際super做了啥:

def super(cls, inst):
 mro = inst.__class__.mro()
 return mro[mro.index(cls) + 1]

換而言之, super方法實(shí)際是調(diào)用了cls的在MRO表中的下一個(gè)類. 如果是簡單一條線的單繼承, 那就是父類->父類一個(gè)一個(gè)地下去羅. 但對(duì)于多繼承, 就要遵循MRO表中的順序了. 以上面的D的調(diào)用為例:

d的初始化

-> D (進(jìn)入D) super(D,self)
-> 父類B (進(jìn)入B) super(B,self)
-> 父類C (進(jìn)入C) super(C,self)
-> 父父類A (進(jìn)入A)  (退出A) # 如有繼續(xù)super(A,self)  -> object (停了)
-> (退出C)
-> (退出B)
-> (退出D)

所以, 在MRO表中的超類初始化函數(shù)只執(zhí)行了一次!

那么, MRO的順序究竟是怎么定的呢? 這個(gè)可以參考官方說明The Python 2.3 Method Resolution Order . 基本就是, 計(jì)算出每個(gè)類(從父類到子類的順序)的MRO, 再merge 成一條線. 遵循以下規(guī)則:

在 MRO 中,基類永遠(yuǎn)出現(xiàn)在派生類后面,如果有多個(gè)基類,基類的相對(duì)順序保持不變。 這個(gè)原則包括兩點(diǎn):

1. 基類永遠(yuǎn)在派生類后面
2. 類定義時(shí)的繼承順序影響相對(duì)順序.

如果有以下繼承 (Python中的super用法詳解):

    object
     /   \
    /      A
   |     /   \
  B-1  C-2   D-2
    \   /    /
     E-1    /
        \  /
          F

那么MRO是: F -> E -> B -> C -> D -> A -> object

怎么解釋呢?

根據(jù)官方的方法, 是:

L(O) = O
L(B) = B O
L(A) = A O
L(C) = C A O
L(D) = D A O
L(E) = E + merge(L(B),L(C))
  = E + merge(BO,CAO)
  = E + B + merge(O,CAO)
  = E + B + C + merge(O,AO)
  = E + B + C + A + merge(O,O)
  = E B C A O
L(F) = F + merge(L(E),L(D))
  = F + merge(EBCAO,DAO)
  = F + EBC + merge(AO,DAO)
  = F + EBC + D + merge(AO,AO)
  = F EBC D AO

看起來很復(fù)雜..但還是遵循在 MRO 中,基類永遠(yuǎn)出現(xiàn)在派生類后面,如果有多個(gè)基類,基類的相對(duì)順序保持不變。所以, 我個(gè)人認(rèn)為可以這么想:

  • 先找出最長深度最深的繼承路線F->E->C->A->object. (因?yàn)楸厝?strong>基類永遠(yuǎn)出現(xiàn)在派生類后面)
  • 類似深度優(yōu)先, 定出其余順序: F->E->B->obj, F->D->A-object
  • 如果有多個(gè)基類,基類的相對(duì)順序保持不變, 類似于merge時(shí)優(yōu)先提前面的項(xiàng). 所以排好這些路線: (FEBO, FECAO, FDAO)
  • F->E->B->obj且E(B,C)決定B在C前面.所以F->E->B->C->A->obj (相當(dāng)于F+merge(EBO,ECAO)).
  • F->D->A-object且F(E,D)決定了D在E后, 所以D在E后A前. 因?yàn)橄鄬?duì)順序, 相當(dāng)于FE+merge(BCAO, DAO), 所以FE BC D AO

更多可參考

關(guān)于Python相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Python面向?qū)ο蟪绦蛟O(shè)計(jì)入門與進(jìn)階教程》、《Python數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Python函數(shù)使用技巧總結(jié)》、《Python字符串操作技巧匯總》、《Python編碼操作技巧總結(jié)》及《Python入門與進(jìn)階經(jīng)典教程

希望本文所述對(duì)大家Python程序設(shè)計(jì)有所幫助。

相關(guān)文章

  • pandas把所有大于0的數(shù)設(shè)置為1的方法

    pandas把所有大于0的數(shù)設(shè)置為1的方法

    今天小編就為大家分享一篇pandas把所有大于0的數(shù)設(shè)置為1的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2019-01-01
  • python獲取中文字符串長度的方法

    python獲取中文字符串長度的方法

    今天小編就為大家分享一篇python獲取中文字符串長度的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-11-11
  • python2.7刪除文件夾和刪除文件代碼實(shí)例

    python2.7刪除文件夾和刪除文件代碼實(shí)例

    python刪除文件夾t和刪除文件代碼實(shí)例,大家參考使用吧,運(yùn)行環(huán)境是python2.7
    2013-12-12
  • Python線程下使用鎖的技巧分享

    Python線程下使用鎖的技巧分享

    本篇文章給大家分享了Python線程下使用鎖需要注意的地方,有興趣的朋友們可以學(xué)習(xí)參考下。
    2018-09-09
  • python數(shù)據(jù)處理之Pandas類型轉(zhuǎn)換的實(shí)現(xiàn)

    python數(shù)據(jù)處理之Pandas類型轉(zhuǎn)換的實(shí)現(xiàn)

    本文主要介紹了python數(shù)據(jù)處理之Pandas類型轉(zhuǎn)換的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • Python selenium文件上傳方法匯總

    Python selenium文件上傳方法匯總

    這篇文章主要為大家詳細(xì)介紹了Python selenium文件上傳方法,selenium文件上傳的所有方法進(jìn)行整理,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-09-09
  • pandas df.sample()的使用

    pandas df.sample()的使用

    本文主要介紹了pandas df.sample()的使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • python中實(shí)現(xiàn)指定時(shí)間調(diào)用函數(shù)示例代碼

    python中實(shí)現(xiàn)指定時(shí)間調(diào)用函數(shù)示例代碼

    函數(shù)function是python編程核心內(nèi)容之一,也是比較重要的一塊。下面這篇文章主要給大家介紹了關(guān)于python中實(shí)現(xiàn)指定時(shí)間調(diào)用函數(shù)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-09-09
  • python輸出帶有顏色字體的三種方法

    python輸出帶有顏色字體的三種方法

    在使用python運(yùn)維與開發(fā)的過程中,經(jīng)常需要打印顯示各種信息,海量的信息堆砌在控制臺(tái)中,就會(huì)導(dǎo)致各種信息都顯示在一起,降低了重要信息的可讀性,這時(shí)候如果能給重要的信息加上差異的字體顏色,那么就會(huì)更加顯眼,所以本文給大家介紹了python輸出帶有顏色文字的三種方法
    2024-05-05
  • Python中日期和時(shí)間的互相轉(zhuǎn)換操作方法

    Python中日期和時(shí)間的互相轉(zhuǎn)換操作方法

    Python的datetime模塊提供了一套強(qiáng)大而靈活的工具,使我們能夠輕松地在不同的時(shí)間表示形式間相互轉(zhuǎn)換,并進(jìn)行復(fù)雜的時(shí)間計(jì)算,本文通過一個(gè)實(shí)用的例子向大家展示如何在Python中高效地進(jìn)行這些操作,感興趣的朋友一起看看吧
    2024-05-05

最新評(píng)論

太湖县| 句容市| 孟连| 张家界市| 平遥县| 中江县| 宜昌市| 泰安市| 南昌市| 徐汇区| 平南县| 蒲江县| 汶上县| 台南县| 沅江市| 台湾省| 平阳县| 酒泉市| 河曲县| 永顺县| 北京市| 启东市| 鄂州市| 宣化县| 岑巩县| 郁南县| 紫阳县| 紫云| 亳州市| 清河县| 内江市| 萍乡市| 铁岭县| 玉林市| 石嘴山市| 宁河县| 石城县| 隆回县| 安泽县| 东山县| 广南县|