Python中的super()面向?qū)ο缶幊?/h1>
更新時(shí)間:2021年09月06日 09:16:59 作者:小菠蘿測(cè)試筆記
這篇文章主要介紹了Python的面向?qū)ο缶幊?super,super在Pyhon是一個(gè)特殊的的類,想具體了解的朋友請(qǐng)參考下面文章內(nèi)容
Python super()面向?qū)ο缶幊?br />
一、為什么要用 super()
當(dāng)子類重寫了父類方法時(shí),又想調(diào)用父類的同名方法時(shí),就需要用到 super()
二、什么是 super
- 在 Python 中,super 是一個(gè)
特殊的類
- super() 就是使用 super 類創(chuàng)建出來的對(duì)象
- 實(shí)際應(yīng)用的場(chǎng)景:子類在重寫父類方法時(shí),調(diào)用父類方法
三、繼承中使用 super
1、實(shí)例方法使用 super
類圖

實(shí)際代碼
class A:
def __init__(self):
self.n = 1
def add(self, m):
print(f'AAA [self] is {id(self)}')
print(f'AAA [self.n] is {self.n}')
self.n += m
class B(A):
def __init__(self):
self.n = 100
# 重寫父類方法
def add(self, m):
# 子類特有代碼
print(f'BBB [self] is {id(self)}')
print(f'BBB [self.n] is {self.n}')
# 調(diào)用父類方法
super().add(m)
self.n += m
b = B()
b.add(2)
print(b.n)
# 輸出結(jié)果
BBB [self] is 4489158560
BBB [self.n] is 100
AAA [self] is 4489158560
AAA [self.n] is 100
104
super().add() 的確調(diào)用了父類方法
重點(diǎn):此時(shí)父類方法的 self 并不是父類實(shí)例對(duì)象,而是子類實(shí)例對(duì)象
2、構(gòu)造方法使用 super
class Animal:
def __init__(self, name):
self.name = name
def prints(self):
print("Animale name is ", self.name)
class Dog(Animal):
def __init__(self, name, age):
# 調(diào)用父類的 init 構(gòu)造方法
super(Dog, self).__init__(name)
self.age = age
def prints(self):
# 調(diào)用父類的方法
super(Dog, self).prints()
print("Dog age is ", self.age)
dog = Dog("小汪", 10)
dog.prints()
# 輸出結(jié)果
Animale name is 小汪
Dog age is 10
這里用了 super(子類名, self) ,和上面的 super() 是一樣效果
調(diào)用父類方法有兩種方式
- super().父類方法()
- super(子類名, self).父類方法()
其實(shí)還有第三種
在 Python 2.x 的時(shí)候,如果需要調(diào)用父類的方法,還可以用
父類名.方法(self)
- 這種方式,Python 3.x 還是支持的
- 過不不推薦,因?yàn)楦割惷l(fā)生變化的話,方法調(diào)用位置的類名也要同步修改
通過父類名調(diào)用父類方法(不推薦)
class Animal:
def __init__(self, name):
self.name = name
def prints(self):
print("Animale name is ", self.name)
class Dog(Animal):
def __init__(self, name, age):
# 調(diào)用父類的 init 構(gòu)造方法
Animal.__init__(self, name)
self.age = age
def prints(self):
# 調(diào)用父類的方法
Animal.prints(self)
print("Dog age is ", self.age)
dog = Dog("小汪", 10)
dog.prints()
# 輸出結(jié)果
Animale name is 小汪
Dog age is 10
通過父類名調(diào)用的這種方式,是需要傳 self 參數(shù)的哦
溫馨提示:
在開發(fā)時(shí), 父類名.方法() , super().方法() 兩種方式不要混用哈
靈魂拷問一:既然已經(jīng)重寫了子類的構(gòu)造方法,為什么還要去調(diào)用 super?
子類需要重寫父類方法來實(shí)現(xiàn)子類獨(dú)有的功能,但同時(shí)又需要依賴父類方法來完成某些邏輯
實(shí)際栗子
- 在實(shí)現(xiàn)多線程的時(shí)候(后面會(huì)詳細(xì)展開說多線程)
- 父類 Thread 的構(gòu)造方法包含了很多邏輯代碼
- 子線程雖然需要實(shí)現(xiàn)子類獨(dú)有功能,但仍需父類方法來處理其他邏輯

from threading import Thread
class MyThread(Thread):
def __init__(self, name):
# 1、實(shí)現(xiàn)子類獨(dú)有功能
print("子類線程 %s" % name)
# 2、需要依賴父類方法完成其他功能
super().__init__(name=name)
四、多繼承中使用 super
類圖

實(shí)際代碼
# 多繼承
class Animal:
def __init__(self, animalName):
print(animalName, 'is an animal.')
# Mammal 繼承 Animal
class Mammal(Animal):
def __init__(self, mammalName):
print(mammalName, 'is a mammal.')
super().__init__(mammalName)
# CannotFly 繼承 Mammal
class CannotFly(Mammal):
def __init__(self, mammalThatCantFly):
print(mammalThatCantFly, "cannot fly.")
super().__init__(mammalThatCantFly)
# CannotSwim 繼承 Mammal
class CannotSwim(Mammal):
def __init__(self, mammalThatCantSwim):
print(mammalThatCantSwim, "cannot swim.")
super().__init__(mammalThatCantSwim)
# Cat 繼承 CannotSwim 和 CannotFly
class Cat(CannotSwim, CannotFly):
def __init__(self):
print('I am a cat.');
super().__init__('Cat')
# Driver code
cat = Cat()
print('')
bat = CannotSwim('Bat')
# 輸出結(jié)果
I am a cat.
Cat cannot swim.
Cat cannot fly.
Cat is a mammal.
Cat is an animal.
Bat cannot swim.
Bat is a mammal.
Bat is an animal.
好像挺奇怪的,從輸出結(jié)果看,為什么 CannotSwim 類里面的 super().__init__() 調(diào)用的是 CannotFly 類里面的方法呢?不是應(yīng)該調(diào)用 CannotSwim 的父類 Mamal 的方法嗎?
靈魂拷問二:super 的執(zhí)行順序到底是什么?
- 其實(shí) super() 并不一定調(diào)用父類的方法
- super() 是根據(jù)類的 MRO 方法搜索順序來決定調(diào)用誰的
- super() 真正調(diào)用的是 MRO 中的下一個(gè)類,而不一定是父類
- 當(dāng)然,這種情況只會(huì)出現(xiàn)在多繼承
先來看看 Cat 的 MRO
print(Cat.__mro__)
(<class '__main__.Cat'>, <class '__main__.CannotSwim'>, <class '__main__.CannotFly'>, <class '__main__.Mammal'>, <class '__main__.Animal'>, <class 'object'>)
從 Cat 的 MRO 可以看到
- CannotSwim 后面跟的是 CannotFly 而不是 Mamal
- 所以 CannotSwim 類里面的 super() 會(huì)調(diào)用 CannotFly 里面的方法
多繼承的栗子二
實(shí)際代碼
class A:
def __init__(self):
self.n = 2
def add(self, m):
# 第四步
# 來自 D.add 中的 super
# self == d, self.n == d.n == 5
print('self is {0} @AAA.add'.format(self))
self.n += m
# d.n == 7
class C(A):
def __init__(self):
self.n = 4
def add(self, m):
# 第三步
# 來自 B.add 中的 super
# self == d, self.n == d.n == 5
print('self is {0} @CCC.add'.format(self))
# 等價(jià)于 suepr(C, self).add(m)
# self 的 MRO 是 [D, B, C, A, object]
# 從 C 之后的 [A, object] 中查找 add 方法
super().add(m)
# 第五步
# d.n = 7
self.n += 4
# d.n = 11
class B(A):
def __init__(self):
self.n = 3
def add(self, m):
# 第二步
# 來自 D.add 中的 super
# self == d, self.n == d.n == 5
print('self is {0} @BBB.add'.format(self))
# self 的 MRO 是 [D, B, C, A, object]
# 從 B 之后的 [C, A, object] 中查找 add 方法
# 從 C 找 add 方法
super().add(m)
# 第六步
# d.n = 11
self.n += 3
# d.n = 14
class D(B, C):
def __init__(self):
self.n = 5
def add(self, m):
# 第一步
print('self is {0} @DDD.add'.format(self))
# self 的 MRO 是 [D, B, C, A, object]
# 從 D 之后的 [B, C, A, object] 中查找 add 方法
# 從 B 找 add 方法
super().add(m)
# 第七步
# d.n = 14
self.n += 5
# self.n = 19
d = D()
d.add(2)
print(d.n)
先看看 D 類的 MRO
print(D.__mro__)
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
輸出結(jié)果
self is <__main__.D object at 0x10c14a190> @DDD.add
self is <__main__.D object at 0x10c14a190> @BBB.add
self is <__main__.D object at 0x10c14a190> @CCC.add
self is <__main__.D object at 0x10c14a190> @AAA.add
19
調(diào)用順序的確是 D、B、C、A
執(zhí)行順序
class D(B, C): class B(A): class C(A): class A:
def add(self, m): def add(self, m): def add(self, m): def add(self, m):
super().add(m) 1.---> super().add(m) 2.---> super().add(m) 3.---> self.n += m
self.n += 5 <------6. self.n += 3 <----5. self.n += 4 <----4. <--|
(14+5=19) (11+3=14) (7+4=11) (5+2=7)
執(zhí)行順序圖

到此這篇關(guān)于Python super()面向?qū)ο缶幊痰奈恼戮徒榻B到這了,更多相關(guān)Python super()內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
-
numpy多項(xiàng)式擬合函數(shù)polyfit的使用方法代碼
這篇文章主要給大家介紹了關(guān)于numpy多項(xiàng)式擬合函數(shù)polyfit的使用方法,np.polyfit是Numpy庫中的一個(gè)函數(shù),用于在最小二乘意義下擬合多項(xiàng)式曲線到數(shù)據(jù)點(diǎn)集,需要的朋友可以參考下 2024-01-01
-
Python學(xué)習(xí)教程之常用的內(nèi)置函數(shù)大全
python給我們提供了很多已經(jīng)定義好的函數(shù),下面這篇文章主要給大家介紹了關(guān)于Python學(xué)習(xí)教程之一些常用的內(nèi)置函數(shù),文中分享了關(guān)于數(shù)學(xué)函數(shù)、功能函數(shù)、類型轉(zhuǎn)換函數(shù)、字符串處理和序列處理函數(shù)的相關(guān)資料,需要的朋友可以參考借鑒,下面來一起看看吧。 2017-07-07
-
詳解如何從TensorFlow的mnist數(shù)據(jù)集導(dǎo)出手寫體數(shù)字圖片
這篇文章主要介紹了詳解如何從TensorFlow的mnist數(shù)據(jù)集導(dǎo)出手寫體數(shù)字圖片,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧 2019-08-08
-
圖文詳解Python中模塊或py文件導(dǎo)入(超詳細(xì)!)
導(dǎo)入文件目的就是為了執(zhí)行文件,下面這篇文章主要給大家介紹了關(guān)于Python中模塊或py文件導(dǎo)入的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下 2023-04-04
-
教你如何用Pytorch搭建數(shù)英混合驗(yàn)證碼圖片識(shí)別模型
大家都知道checkpoints存放的是模型文件,data存放的是數(shù)據(jù)集,本文給大家分享如何利用Pytorch搭建數(shù)英混合驗(yàn)證碼圖片識(shí)別模型包括普通卷積模塊,深度可分離卷積模塊,空間通道注意力模塊,殘差模塊,感興趣的朋友跟隨小編一起看看吧 2024-04-04
-
分享4個(gè)Python中的非常好用的自動(dòng)化腳本
這篇文章為大家準(zhǔn)備了4個(gè)很棒的Python自動(dòng)化腳本,可以解決這些問題。文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,需要的可以參考一下 2022-11-11
最新評(píng)論
Python super()面向?qū)ο缶幊?br />
一、為什么要用 super()
當(dāng)子類重寫了父類方法時(shí),又想調(diào)用父類的同名方法時(shí),就需要用到 super()
二、什么是 super
- 在 Python 中,super 是一個(gè)
特殊的類 - super() 就是使用 super 類創(chuàng)建出來的對(duì)象
- 實(shí)際應(yīng)用的場(chǎng)景:子類在重寫父類方法時(shí),調(diào)用父類方法
三、繼承中使用 super
1、實(shí)例方法使用 super
類圖

實(shí)際代碼
class A:
def __init__(self):
self.n = 1
def add(self, m):
print(f'AAA [self] is {id(self)}')
print(f'AAA [self.n] is {self.n}')
self.n += m
class B(A):
def __init__(self):
self.n = 100
# 重寫父類方法
def add(self, m):
# 子類特有代碼
print(f'BBB [self] is {id(self)}')
print(f'BBB [self.n] is {self.n}')
# 調(diào)用父類方法
super().add(m)
self.n += m
b = B()
b.add(2)
print(b.n)
# 輸出結(jié)果
BBB [self] is 4489158560
BBB [self.n] is 100
AAA [self] is 4489158560
AAA [self.n] is 100
104
super().add() 的確調(diào)用了父類方法
重點(diǎn):此時(shí)父類方法的 self 并不是父類實(shí)例對(duì)象,而是子類實(shí)例對(duì)象
2、構(gòu)造方法使用 super
class Animal:
def __init__(self, name):
self.name = name
def prints(self):
print("Animale name is ", self.name)
class Dog(Animal):
def __init__(self, name, age):
# 調(diào)用父類的 init 構(gòu)造方法
super(Dog, self).__init__(name)
self.age = age
def prints(self):
# 調(diào)用父類的方法
super(Dog, self).prints()
print("Dog age is ", self.age)
dog = Dog("小汪", 10)
dog.prints()
# 輸出結(jié)果
Animale name is 小汪
Dog age is 10
這里用了 super(子類名, self) ,和上面的 super() 是一樣效果
調(diào)用父類方法有兩種方式
- super().父類方法()
- super(子類名, self).父類方法()
其實(shí)還有第三種
在 Python 2.x 的時(shí)候,如果需要調(diào)用父類的方法,還可以用
父類名.方法(self)
- 這種方式,Python 3.x 還是支持的
- 過不不推薦,因?yàn)楦割惷l(fā)生變化的話,方法調(diào)用位置的類名也要同步修改
通過父類名調(diào)用父類方法(不推薦)
class Animal:
def __init__(self, name):
self.name = name
def prints(self):
print("Animale name is ", self.name)
class Dog(Animal):
def __init__(self, name, age):
# 調(diào)用父類的 init 構(gòu)造方法
Animal.__init__(self, name)
self.age = age
def prints(self):
# 調(diào)用父類的方法
Animal.prints(self)
print("Dog age is ", self.age)
dog = Dog("小汪", 10)
dog.prints()
# 輸出結(jié)果
Animale name is 小汪
Dog age is 10
通過父類名調(diào)用的這種方式,是需要傳 self 參數(shù)的哦
溫馨提示:
在開發(fā)時(shí), 父類名.方法() , super().方法() 兩種方式不要混用哈
靈魂拷問一:既然已經(jīng)重寫了子類的構(gòu)造方法,為什么還要去調(diào)用 super?
子類需要重寫父類方法來實(shí)現(xiàn)子類獨(dú)有的功能,但同時(shí)又需要依賴父類方法來完成某些邏輯
實(shí)際栗子
- 在實(shí)現(xiàn)多線程的時(shí)候(后面會(huì)詳細(xì)展開說多線程)
- 父類 Thread 的構(gòu)造方法包含了很多邏輯代碼
- 子線程雖然需要實(shí)現(xiàn)子類獨(dú)有功能,但仍需父類方法來處理其他邏輯

from threading import Thread
class MyThread(Thread):
def __init__(self, name):
# 1、實(shí)現(xiàn)子類獨(dú)有功能
print("子類線程 %s" % name)
# 2、需要依賴父類方法完成其他功能
super().__init__(name=name)
四、多繼承中使用 super
類圖

實(shí)際代碼
# 多繼承
class Animal:
def __init__(self, animalName):
print(animalName, 'is an animal.')
# Mammal 繼承 Animal
class Mammal(Animal):
def __init__(self, mammalName):
print(mammalName, 'is a mammal.')
super().__init__(mammalName)
# CannotFly 繼承 Mammal
class CannotFly(Mammal):
def __init__(self, mammalThatCantFly):
print(mammalThatCantFly, "cannot fly.")
super().__init__(mammalThatCantFly)
# CannotSwim 繼承 Mammal
class CannotSwim(Mammal):
def __init__(self, mammalThatCantSwim):
print(mammalThatCantSwim, "cannot swim.")
super().__init__(mammalThatCantSwim)
# Cat 繼承 CannotSwim 和 CannotFly
class Cat(CannotSwim, CannotFly):
def __init__(self):
print('I am a cat.');
super().__init__('Cat')
# Driver code
cat = Cat()
print('')
bat = CannotSwim('Bat')
# 輸出結(jié)果
I am a cat.
Cat cannot swim.
Cat cannot fly.
Cat is a mammal.
Cat is an animal.
Bat cannot swim.
Bat is a mammal.
Bat is an animal.
好像挺奇怪的,從輸出結(jié)果看,為什么 CannotSwim 類里面的 super().__init__() 調(diào)用的是 CannotFly 類里面的方法呢?不是應(yīng)該調(diào)用 CannotSwim 的父類 Mamal 的方法嗎?
靈魂拷問二:super 的執(zhí)行順序到底是什么?
- 其實(shí) super() 并不一定調(diào)用父類的方法
- super() 是根據(jù)類的 MRO 方法搜索順序來決定調(diào)用誰的
- super() 真正調(diào)用的是 MRO 中的下一個(gè)類,而不一定是父類
- 當(dāng)然,這種情況只會(huì)出現(xiàn)在多繼承
先來看看 Cat 的 MRO
print(Cat.__mro__) (<class '__main__.Cat'>, <class '__main__.CannotSwim'>, <class '__main__.CannotFly'>, <class '__main__.Mammal'>, <class '__main__.Animal'>, <class 'object'>)
從 Cat 的 MRO 可以看到
- CannotSwim 后面跟的是 CannotFly 而不是 Mamal
- 所以 CannotSwim 類里面的 super() 會(huì)調(diào)用 CannotFly 里面的方法
多繼承的栗子二
實(shí)際代碼
class A:
def __init__(self):
self.n = 2
def add(self, m):
# 第四步
# 來自 D.add 中的 super
# self == d, self.n == d.n == 5
print('self is {0} @AAA.add'.format(self))
self.n += m
# d.n == 7
class C(A):
def __init__(self):
self.n = 4
def add(self, m):
# 第三步
# 來自 B.add 中的 super
# self == d, self.n == d.n == 5
print('self is {0} @CCC.add'.format(self))
# 等價(jià)于 suepr(C, self).add(m)
# self 的 MRO 是 [D, B, C, A, object]
# 從 C 之后的 [A, object] 中查找 add 方法
super().add(m)
# 第五步
# d.n = 7
self.n += 4
# d.n = 11
class B(A):
def __init__(self):
self.n = 3
def add(self, m):
# 第二步
# 來自 D.add 中的 super
# self == d, self.n == d.n == 5
print('self is {0} @BBB.add'.format(self))
# self 的 MRO 是 [D, B, C, A, object]
# 從 B 之后的 [C, A, object] 中查找 add 方法
# 從 C 找 add 方法
super().add(m)
# 第六步
# d.n = 11
self.n += 3
# d.n = 14
class D(B, C):
def __init__(self):
self.n = 5
def add(self, m):
# 第一步
print('self is {0} @DDD.add'.format(self))
# self 的 MRO 是 [D, B, C, A, object]
# 從 D 之后的 [B, C, A, object] 中查找 add 方法
# 從 B 找 add 方法
super().add(m)
# 第七步
# d.n = 14
self.n += 5
# self.n = 19
d = D()
d.add(2)
print(d.n)
先看看 D 類的 MRO
print(D.__mro__) (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
輸出結(jié)果
self is <__main__.D object at 0x10c14a190> @DDD.add self is <__main__.D object at 0x10c14a190> @BBB.add self is <__main__.D object at 0x10c14a190> @CCC.add self is <__main__.D object at 0x10c14a190> @AAA.add 19
調(diào)用順序的確是 D、B、C、A
執(zhí)行順序
class D(B, C): class B(A): class C(A): class A: def add(self, m): def add(self, m): def add(self, m): def add(self, m): super().add(m) 1.---> super().add(m) 2.---> super().add(m) 3.---> self.n += m self.n += 5 <------6. self.n += 3 <----5. self.n += 4 <----4. <--| (14+5=19) (11+3=14) (7+4=11) (5+2=7)
執(zhí)行順序圖

到此這篇關(guān)于Python super()面向?qū)ο缶幊痰奈恼戮徒榻B到這了,更多相關(guān)Python super()內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
numpy多項(xiàng)式擬合函數(shù)polyfit的使用方法代碼
這篇文章主要給大家介紹了關(guān)于numpy多項(xiàng)式擬合函數(shù)polyfit的使用方法,np.polyfit是Numpy庫中的一個(gè)函數(shù),用于在最小二乘意義下擬合多項(xiàng)式曲線到數(shù)據(jù)點(diǎn)集,需要的朋友可以參考下2024-01-01
Python學(xué)習(xí)教程之常用的內(nèi)置函數(shù)大全
python給我們提供了很多已經(jīng)定義好的函數(shù),下面這篇文章主要給大家介紹了關(guān)于Python學(xué)習(xí)教程之一些常用的內(nèi)置函數(shù),文中分享了關(guān)于數(shù)學(xué)函數(shù)、功能函數(shù)、類型轉(zhuǎn)換函數(shù)、字符串處理和序列處理函數(shù)的相關(guān)資料,需要的朋友可以參考借鑒,下面來一起看看吧。2017-07-07
詳解如何從TensorFlow的mnist數(shù)據(jù)集導(dǎo)出手寫體數(shù)字圖片
這篇文章主要介紹了詳解如何從TensorFlow的mnist數(shù)據(jù)集導(dǎo)出手寫體數(shù)字圖片,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08
圖文詳解Python中模塊或py文件導(dǎo)入(超詳細(xì)!)
導(dǎo)入文件目的就是為了執(zhí)行文件,下面這篇文章主要給大家介紹了關(guān)于Python中模塊或py文件導(dǎo)入的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-04-04
教你如何用Pytorch搭建數(shù)英混合驗(yàn)證碼圖片識(shí)別模型
大家都知道checkpoints存放的是模型文件,data存放的是數(shù)據(jù)集,本文給大家分享如何利用Pytorch搭建數(shù)英混合驗(yàn)證碼圖片識(shí)別模型包括普通卷積模塊,深度可分離卷積模塊,空間通道注意力模塊,殘差模塊,感興趣的朋友跟隨小編一起看看吧2024-04-04
分享4個(gè)Python中的非常好用的自動(dòng)化腳本
這篇文章為大家準(zhǔn)備了4個(gè)很棒的Python自動(dòng)化腳本,可以解決這些問題。文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,需要的可以參考一下2022-11-11

