日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

pythonsuper函数_认识python中的super函数

發(fā)布時間:2024/9/3 python 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 pythonsuper函数_认识python中的super函数 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

需求分析

在類繼承中,存在這么一種情況:

class Human(object):

def Move(self):

print("我會走路...")

class Man(Human):

def Move(self):

print("我會跑步...")

man().Move()

輸出:

我會跑步...

人先會走路再會跑步的。如果你想調(diào)用Man().Move()時輸出以下要怎么做?

我會走路...

我會跑步...

這時,其實便需要調(diào)用父類Human的Move()方法了。我們知道,在子類中,會覆父類的同名方法。即子類Man里的Move()方法將父類Human中的同名方法Move()覆蓋了。要想同時使得兩個方法都奏效,可以在子類中主動調(diào)用父類中的Move()方法。其實很簡單,在類Man中加點東西就行了,如下:

class Human(object):

def Move(self):

print("我會走路...")

class Man(Human):

def Move(self):

Human.Move(self)

print("我會跑步...")

Man().Move()

output:

我會走路...

我會跑步...

代碼中的Human.Move(self)便是在子類Man中主動跟調(diào)用父類的方法。我來解釋一下這句代碼:

Human.Move(self)中Human是類,由類直接調(diào)用Move方法,這是未綁定的調(diào)用。

Human.Move(self)中的self其實是Man的一個實例Man(),一個個類的實例化是這樣的m=Man(),其中,m和Man()都是類Man的實例。

但是,這種方法有一個弊端。比如,如果父類Human吃飽沒事干給自己換個名字叫GoodHuman,那么麻煩就來了,你不僅要把Man(Human)改為Man(GoodHuman),還要把Human.Move(self)改為GoodHuman.Move(self)。

當然,這里的例子改起來是沒什么可怕。但萬一在一些項目里像Human.Move(self)這類型的方法很多的話,你要一個一個改?

有沒有什么辦法,使得在父類更改名稱時,子類只要改類似Man(Human)一處就好?

super()出場

super()的作用是:在類的繼承中,如果重定義某個方法,該方法會覆蓋父類的同名方法,但有時,我們希望能同時實現(xiàn)父類的功能,這時,我們就需要調(diào)用父類的方法了,可通過使用 super 來實現(xiàn)。

調(diào)用super()地常用格式是:

class C(B):

def meth(self, arg):

super(C, self).meth(arg)

現(xiàn)在,只要將代碼改為以下,就不怕父類名稱地變化了。(輸出結(jié)果和上述一樣)

class Human(object):

def Move(self):

print("我會走路...")

class Man(Human):

def Move(self):

super(Man, self).Move()

print("我會跑步...")

稍微深入

上面地例子很簡單,因為類Man繼承地父類已有一個。當繼承關(guān)系變復雜時,(比如同時繼承很多個類,繼承的類又繼承其他類等等...),便要知道super()是怎么處理繼承順序了。

看這個例子:

class Base(object):

def __init__(self):

print("enter Base")

print("leave Base")

class A(Base):

def __init__(self):

print("enter A")

super(A, self).__init__()

print("leave A")

class B(Base):

def __init__(self):

print("enter B")

super(B, self).__init__()

print("leave B")

class C(A, B):

def __init__(self):

print("enter C")

super(C, self).__init__()

print("leave C")

按照前面的思路。我們意淫的輸出應該是:

enter C

enter A

enter Base

leave Base

leave A

enter B

enter Base

leave Base

leave B

leave C

但實際輸出卻是:

enter C

enter A

enter B

enter Base

leave Base

leave B

leave A

leave C

我在這里提一個疑問:

**enter A的下一句為什么不是enter Base而是enter B么? **

揭開super的面紗

其實,對于你定義的每一個類,Python 會用方法解析順序(Method Resolution Order, MRO)計算出一個列表,它代表了類繼承的順序,我們可以使用下面的方式獲得某個類的 MRO 列表:

>>>print(C.mro())

[, , , , ]

[Finished in 0.2s]

一個類的 MRO 列表就是合并所有父類的 MRO 列表,并遵循以下三條原則:

子類永遠在父類前面;

如果有多個父類,會根據(jù)它們在列表中的順序被檢查;

如果對下一個類存在兩個合法的選擇,選擇第一個父類.

我們查看super函數(shù)的代碼:

ef super(cls, inst):

mro = inst.__class__.mro()

return mro[mro.index(cls) + 1]

其中,cls 代表類,inst 代表實例,上面的代碼做了兩件事:

獲取 inst 的 MRO 列表;

查找 cls 在當前 MRO 列表中的 index, 并返回它的下一個類,即 mro[index + 1]。

當你使用 super(cls, inst) 時,Python 會在 inst 的 MRO 列表上搜索 cls 的下一個類。

現(xiàn)在我們來通過一步步追蹤來回答上面提出的答案:

做法很簡單:

1, 修改一下代碼:

class Base(object):

def __init__(self):

print("enter Base")

print("leave Base")

print(self)

class A(Base):

def __init__(self):

print("enter A")

print(self)

super(A, self).__init__()

print("leave A")

class B(Base):

def __init__(self):

print("enter B")

print(self)

super(B, self).__init__()

print("leave B")

class C(A, B):

def __init__(self):

print("enter C")

print(self)

super(C, self).__init__()

print("leave C")

c = C()

print(hex(id(c)))

看輸出:

enter C

<__main__.C object at 0x000001C614CAB7F0>

enter A

<__main__.C object at 0x000001C614CAB7F0>

enter B

<__main__.C object at 0x000001C614CAB7F0>

enter Base

leave Base

<__main__.C object at 0x000001C614CAB7F0>

leave B

leave A

leave C

0x1c614cab7f0

在這里塞了這么多代碼,就為了說明兩件事:

在A,B,C,Base這四個類中,self都是<__main__.C object at 0x000001C614CAB7F0>這個對象。

<__main__.C object at 0x000001C614CAB7F0>是類C的實例c(c的id輸出是0x1c614cab7f0,說明它們是同樣的東西)。實例c也就是整個過程的發(fā)起者。

到了這里,就可以回答問題了:

首先看類C的__init__方法:

super(C, self).__init__()

這里的 self 是當前 C 的實例,self.__class__.mro() 結(jié)果是:

[__main__.C, __main__.A, __main__.B, __main__.Base, object]

可以看到,C 的下一個類是 A,于是,跳到了 A 的 __init__,這時會打印出 enter A,并執(zhí)行下面一行代碼:

super(A, self).__init__()

注意,這里的 self 也是當前 C 的實例,MRO 列表跟上面是一樣的,搜索 A 在 MRO 中的下一個類,發(fā)現(xiàn)是 B,于是,跳到了 B 的__init__,這時會打印出enter B,而不是enter Base。

總結(jié)

super和父類沒有實質(zhì)性的關(guān)聯(lián)。通過上面分析。我們知道super函數(shù)是根據(jù)self以及該self對應的方法解析順序mro來工作的。

再強調(diào)一下,self是一個實例對象,在這里就是實例c(上面代碼有一句c=C()),整個過程的發(fā)起者。

版權(quán):保留所有權(quán),轉(zhuǎn)載請注明出處!

總結(jié)

以上是生活随笔為你收集整理的pythonsuper函数_认识python中的super函数的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。