摘要:我們的小明,就這樣被一次次的往上傳導(dǎo)到了每一級的函數(shù)中,于是每一級打印的都是或者說小明傻傻的分割線更新之前的說法并不準(zhǔn)確,參見和準(zhǔn)確的說
super 的工作原理如下:
def super(cls, inst): mro = inst.__class__.mro() return mro[mro.index(cls) + 1]
其中,cls 代表類,inst 代表實(shí)例,上面的代碼做了兩件事:
獲取 inst 的 MRO 列表
查找 cls 在當(dāng)前 MRO 列表中的 index, 并返回它的下一個(gè)類,即 mro[index + 1]
當(dāng)你使用 super(cls, inst) 時(shí),Python 會在 inst 的 MRO 列表上搜索 cls 的下一個(gè)類。
下面看一個(gè)例子:
class A: def __init__(self): self.n = 2 def add(self, m): print(" self is {0} @A.add".format(self)) self.n += m class B(A): def __init__(self): self.n = 3 def add(self, m): print(" self is {0} @B.add".format(self)) super(B, self).add(m) self.n += 3 class C(A): def __init__(self): self.n = 4 def add(self, m): print(" self is {0} @C.add".format(self)) super(C, self).add(m) self.n += 4 class D(B, C): def __init__(self): self.n = 5 def add(self, m): print(" self is {0} @D.add".format(self)) print(super(D, self).__self__) print(super(D, self).__thisclass__) super(D, self).add(m) self.n += 5 if __name__ == "__main__": print(D.mro()) d = D() d.add(2) # 等于是: D.add(d, 2) print(d.n)
結(jié)果是:
[, , , , ] <__main__.D object at 0x101ef16d8> self is <__main__.D object at 0x101ef16d8> @D.add <__main__.D object at 0x101ef16d8> self is <__main__.D object at 0x101ef16d8> @B.add self is <__main__.D object at 0x101ef16d8> @C.add self is <__main__.D object at 0x101ef16d8> @A.add 19
來通過這個(gè)結(jié)果具體說幾點(diǎn)細(xì)節(jié):
print(D.mro()) 首先打印出 D類的 mro 列表:[
然后我們通過d = D()創(chuàng)建一個(gè)D類的實(shí)例: <__main__.D object at 0x101ef16d8>; 為了方便, 我們就把這個(gè)實(shí)例object at 0x101ef16d8 叫做 “小明” 吧
召喚d.add(2) 這個(gè)函數(shù)的時(shí)候,D類中add函數(shù)的self實(shí)際上就是這個(gè)剛被創(chuàng)建的小明同學(xué)object at 0x101ef16d8.
那么接下來呢,super(D, self) 就是在 object at 0x101ef16d8 的mro列表中,在小明的MRO列表中, 找到 class D(D類)的下一個(gè) class(類), 這里也就是 class B (B類) 。
注意 mro列表里
每一個(gè) add 函數(shù)打印的都是 self is <__main__.D object at 0x101ef16d8>, 往上追溯的過程中,無論到了哪一級,self始終都是最初創(chuàng)建的那個(gè) D類的實(shí)例。
這是為什么呢?
注意看 print(super(D, self).__self__) 那一行返還的輸出:<__main__.D object at 0x101ef16d8> .
哦哦?! 這他媽的不是小明嗎?
也就是說, super()雖然找到的是B類,召喚的是B類的 add()函數(shù),但它的self仍然是最開始創(chuàng)建的D類實(shí)例(我們的 小明同學(xué)),而且召喚add()這個(gè)函數(shù)時(shí),仍然是把這樣的一個(gè)self傳給了 class B 的 add()函數(shù)。
我們的 “小明”, 就這樣被一次次的往上傳導(dǎo)到了每一級的 add() 函數(shù)中, 于是每一級打印的都是:
self is <__main__.D object at 0x101ef16d8> 或者說: self is 小明
、################ 傻傻的分割線 ##################################
2019-06-23 更新:
之前的說法并不準(zhǔn)確,
參見:https://stackoverflow.com/que...
和
https://stackoverflow.com/que...
準(zhǔn)確的說:
super() requires as its first argument the class whose parents you want to resolve to, and as a second argument the instance of that class to which you"re trying to apply a parent"s method. Here cls is an instance of Meta_1, thus super(Meta_1, ...) means that we want Meta_1"s parents. super(..., cls) specifies the instance that will be bound to that method when it is called (i.e. it will be received as self in __call__(self, ...) ).
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/44085.html
摘要:整個(gè)過程還是比較清晰的,關(guān)鍵是要理解的工作方式,而不是想當(dāng)然地認(rèn)為調(diào)用了父類的方法。小結(jié)事實(shí)上,和父類沒有實(shí)質(zhì)性的關(guān)聯(lián)。 super() 的入門使用 在類的繼承中,如果重定義某個(gè)方法,該方法會覆蓋父類的同名方法,但有時(shí),我們希望能同時(shí)實(shí)現(xiàn)父類的功能,這時(shí),我們就需要調(diào)用父類的方法了,可通過使用 super 來實(shí)現(xiàn),比如: class Animal(object): def __...
摘要:由上面的注釋,可以看出其實(shí)就相當(dāng)于一個(gè)描述符類,而在此刻變成了一個(gè)描述符。調(diào)用這個(gè)方法可以知道,每調(diào)用一次,它都會經(jīng)過描述符類的。基于描述符如何實(shí)現(xiàn)同樣的也是一樣。我想你應(yīng)該對描述符在中的應(yīng)用有了更深的理解。好吧,我承認(rèn)我標(biāo)題黨了。但是這篇文章的知識點(diǎn),你有極大的可能并不知道。 前段時(shí)間,我寫了一篇描述符的入門級文章,從那些文章里你知道了如何定義描述符,且明白了描述符是如何工作的。 如果你還...
摘要:由上面的注釋,可以看出其實(shí)就相當(dāng)于一個(gè)描述符類,而在此刻變成了一個(gè)描述符。調(diào)用這個(gè)方法可以知道,每調(diào)用一次,它都會經(jīng)過描述符類的?;诿枋龇绾螌?shí)現(xiàn)同樣的也是一樣。我想你應(yīng)該對描述符在中的應(yīng)用有了更深的理解。好吧,我承認(rèn)我標(biāo)題黨了。但是這篇文章的知識點(diǎn),你有極大的可能并不知道。 前段時(shí)間,我寫了一篇描述符的入門級文章,從那些文章里你知道了如何定義描述符,且明白了描述符是如何工作的。 如果你還...
摘要:類元編程是指在運(yùn)行時(shí)創(chuàng)建或定制類的技藝。注意在中做元編程時(shí)最好不要用和函數(shù)。三元類基礎(chǔ)知識元類是類元編程最高級的工具使用元類可以創(chuàng)建具有某種特質(zhì)的全新變種,例如抽象基類。建議除非開發(fā)框架,否則不要在生產(chǎn)代碼中定義元類或抽象基類。 導(dǎo)語:本文章記錄了本人在學(xué)習(xí)Python基礎(chǔ)之元編程篇的重點(diǎn)知識及個(gè)人心得,打算入門Python的朋友們可以來一起學(xué)習(xí)并交流。 本文重點(diǎn): 1、了解運(yùn)行時(shí)創(chuàng)建...
摘要:笨辦法學(xué)第版結(jié)構(gòu)非常簡單,共包括個(gè)習(xí)題,其中個(gè)覆蓋了輸入輸出變量和函數(shù)三個(gè)主題,另外個(gè)覆蓋了一些比較高級的話題,如條件判斷循環(huán)類和對象代碼測試及項(xiàng)目的實(shí)現(xiàn)等。最后只想說,學(xué)習(xí)不會辜負(fù)任何人,笨辦法學(xué) 內(nèi)容簡介 《笨辦法學(xué)Python(第3版)》是一本Python入門書籍,適合對計(jì)...
閱讀 2785·2019-08-30 15:52
閱讀 3732·2019-08-29 17:02
閱讀 1986·2019-08-29 13:00
閱讀 1068·2019-08-29 11:07
閱讀 3394·2019-08-27 10:53
閱讀 1900·2019-08-26 13:43
閱讀 1140·2019-08-26 10:22
閱讀 1483·2019-08-23 18:06