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

歡迎訪問 生活随笔!

生活随笔

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

python

python继承和多态_Python 简明教程 --- 21,Python 继承与多态

發布時間:2025/3/12 python 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python继承和多态_Python 简明教程 --- 21,Python 继承与多态 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

程序不是年輕的專利,但是,它屬于年輕。

目錄

我們已經知道封裝,繼承和多態 是面向對象的三大特征,面向對象語言都會提供這些機制。

1,封裝

在這一節介紹類的私有屬性和方法的時候,我們已經講到過封裝。

封裝就是在設計一個類的時候,只允許使用者訪問他需要的方法,將復雜的,沒有必要讓使用者知道的方法隱藏起來。這樣,使用者只需關注他需要的東西,為其屏蔽了復雜性。

私有性就是實現封裝的一種手段,這樣,類的設計者就可以控制類中的哪些屬性和方法可以被使用者訪問到。一般,類中的屬性,和一些復雜的方法都不會暴露給使用者。

由于前邊的章節介紹過封裝,這里就不再舉例說明了。

2,繼承

通過繼承的機制,可使得子類輕松的擁有父類中的屬性和方法。繼承也是一種代碼復用的方式。

Python 支持類的繼承,繼承的類叫做子類或者派生類,被繼承的類叫做父類或基類。

繼承的語法如下:

class 子類名(父類名):

pass

在子類名后邊的括號中,寫入要繼承的父類。

object 類

在Python 的繼承體系中,object 是最頂層類,它是所有類的父類。在定義一個類時,如果沒有繼承任何類,會默認繼承object 類。如下兩種定義方式是等價的:

# 沒有顯示繼承任何類,默認繼承 object

class A1:

pass

# 顯示繼承 object

class A2(object):

pass

每個類中都有一個mro 方法,該方法可以打印類的繼承關系(順序)。我們來查看A1 和 A2 的繼承關系:

>>> A1.mro()

[, ]

>>>

>>> A2.mro()

[, ]

可見這兩個類都繼承了 object 類。

繼承中的__init__ 方法

當一個子類繼承一個父類時,如果子類中沒有定義__init__,在創建子類的對象時,會調用父類的__init__ 方法,如下:

#! /usr/bin/env python3

class A(object):

def __init__(self):

print('A.__init__')

class B(A):

pass

以上代碼中,B 繼承了A,A 中有__init__ 方法,B 中沒有__init__ 方法,創建類B 的對象b:

>>> b = B()

A.__init__

可見A 中的__init__ 被執行了。

方法覆蓋

如果類B 中也定義了__init__ 方法,那么,就只會執行B 中的__init__ 方法,而不會執行A 中的__init__ 方法:

#! /usr/bin/env python3

class A(object):

def __init__(self):

print('A.__init__')

class B(A):

def __init__(self):

print('B.__init__')

此時創建B 的對象b:

>>> b = B()

B.__init__

可見,此時只執行了B 中的__init__ 方法。這其實是方法覆蓋的原因,因為子類中的__init__ 與父類中的__init__ 的參數列表一樣,此時,子類中的方法覆蓋了父類中的方法,所以創建對象b 時,只會執行B 中的__init__ 方法。

當發生繼承關系(即一個子類繼承一個父類)時,如果子類中的一個方法與父類中的一個方法一模一樣(即方法名相同,參數列表也相同),這種情況就是方法覆蓋(子類中的方法會覆蓋父類中的方法)。

方法重載

當方法名與參數列表都一樣時會發生方法覆蓋;當方法名一樣,參數列表不一樣時,會發生方法重載。

在單個類中,代碼如下:

#! /usr/bin/env python3

class A(object):

def __init__(self):

print('A.__init__')

def test(self):

print('test...')

def test(self, i):

print('test... i:%s' % i)

類A 中的兩個test 方法,方法名相同,參數列表不同。

其實這種情況在Java 和 C++ 是允許的,就是方法重載。而在Python 中,雖然在類中這樣寫不會報錯,但實際上,下面的test(self, i) 已經把上面的test(self) 給覆蓋掉了。創建出來的對象只能調用test(self, i),而test(self) 是不存在的。

示例:

>>> a = A() # 創建 A 的對象 a

A.__init__

>>>

>>> a.test(123) # 可以調用 test(self, i) 方法

test... i:123

>>>

>>> a.test() # 調用 test(self) 發生異常

Traceback (most recent call last):

File "", line 1, in

TypeError: test() missing 1 required positional argument: 'i'

在繼承關系中,代碼如下:

#! /usr/bin/env python3

class A(object):

def __init__(self):

print('A.__init__')

def test(self):

print('test...')

class B(A):

def __init__(self):

print('B.__init__')

def test(self, i):

print('test... i:%s' % i)

上面代碼中B 繼承了A,B 和 A 中都有一個名為test 的方法,但是參數列表不同。

這種情況跟在單個類中的情況是一樣的,在類B 中,test(self, i) 會覆蓋A 中的test(self),類B 的對象只能調用test(self, i),而不能調用test(self)。

示例:

>>> b = B() # 創建 B 的對象

B.__init__

>>>

>>> b.test(123) # 可以調用 test(self, i) 方法

test... i:123

>>>

>>> b.test() # 調用 test(self) 方法,出現異常

Traceback (most recent call last):

File "", line 1, in

TypeError: test() missing 1 required positional argument: 'i'

super() 方法

super() 方法用于調用父類中的方法。

示例代碼:

#! /usr/bin/env python3

class A(object):

def __init__(self):

print('A.__init__')

def test(self):

print('class_A test...')

class B(A):

def __init__(self):

print('B.__init__')

super().__init__() # 調用父類中的構造方法

def test(self, i):

print('class_B test... i:%s' % i)

super().test() # 調用父類中的 test 方法

演示:

>>> b = B() # 創建 B 的對象

B.__init__ # 調用 B 的構造方法

A.__init__ # 調用 A 的構造方法

>>>

>>> b.test(123) # 調用 B 中的 test 方法

class_B test... i:123

class_A test... # 執行 A 中的 test 方法

is-a 關系

一個子類的對象,同時也是一個父類的對象,這叫做is-a 關系。但是一個父類的對象,不一定是一個子類的對象。

這很好理解,就像,貓一定是動物,但動物不一定是貓。

我們可以使用isinstance() 函數來判斷一個對象是否是一個類的實例。

比如我們有如下兩個類,Cat 繼承了 Animal:

#! /usr/bin/env python3

class Animal(object):

pass

class Cat(Animal):

pass

來看下對象和類之間的從屬關系:

>>> a = Animal() # 創建 Animal 的對象

>>> c = Cat() # 創建 Cat 的對象

>>>

>>> isinstance(a, Animal) # a 一定是 Animal 的實例

True

>>> isinstance(c, Cat) # c 一定是 Cat 的實例

True

>>>

>>> isinstance(c, Animal) # Cat 繼承了 Animal,所以 c 也是 Animal 的實例

True

>>> isinstance(a, Cat) # 但 a 不是 Cat 的實例

False

3,多繼承

多繼承就是一個子類同時繼承多個父類,這樣,這個子類就同時擁有了多個父類的特性。

C++ 語言中允許多繼承,但由于多繼承會使得類的繼承關系變得復雜。因此,到了Java 中,就禁止了多繼承的方式,取而代之的是,在Java 中允許同時繼承多個接口。

Python 中也允許多繼承,語法如下:

# 括號中可以寫多個父類

class 子類名(父類1, 父類2, ...):

pass

我們構造一個如下的繼承關系:

代碼如下:

#! /usr/bin/env python3

class A(object):

def test(self):

print('class_A test...')

class B(A):

def test(self):

print('class_B test...')

class C(A):

def test(self):

print('class_C test...')

class D(B, C):

pass

類A,B,C 中都有test() 方法,D 中沒有test() 方法。

使用D 類中的mro()方法查看繼承關系:

>>> D.mro()

[, , , , ]

創建D 的對象:

>>> d = D()

如果類D 中有test() 方法,那么d.test() 肯定會調用D 中的test() 方法,這種情況很簡單,不用多說。

當類D 中沒有test() 方法時,而它繼承的父類 B 和 C 中都有 test() 方法,此時會調用哪個test() 呢?

>>> d.test()

class_B test...

可以看到d.test() 調用了類B 中的 test() 方法。

實際上這種情況下,Python 解釋器會根據D.mro() 的輸出結果來依次查找test() 方法,即查找順序是D->B->C->A->object。

所以d.test() 調用了類B 中的 test() 方法。

建議:

由于多繼承會使類的繼承關系變得復雜,所以并不提倡過多的使用多繼承。

4,多態

多態從字面上理解就是一個事物可以呈現多種狀態。繼承是多態的基礎。

在上面的例子中,類D 的對象d 調用test() 方法時,沿著繼承鏈(D.mro())查找合適的test() 方法的過程,就是多態的表現過程。

比如,我們有以下幾個類:

Animal:有一個speak() 方法

Cat:繼承Animal 類,有自己的speak() 方法

Dog:繼承Animal 類,有自己的speak() 方法

Duck:繼承Animal 類,有自己的speak() 方法

Cat,Dog,Duck 都屬于動物,因此都繼承Animal,代碼如下:

#! /usr/bin/env python3

class Animal(object):

def speak(self):

print('動物會說話...')

class Cat(Animal):

def speak(self):

print('喵喵...')

class Dog(Animal):

def speak(self):

print('汪汪...')

class Duck(Animal):

def speak(self):

print('嘎嘎...')

def animal_speak(animal):

animal.speak()

我們還定義了一個animal_speak 函數,它接受一個參數animal,在函數內,調用了speak() 方法。

實際上,這種情況下,我們調用animal_speak 函數時,可以為它傳遞Animal 類型的對象,以及任何的Animal 子類的對象。

傳遞Animal 的對象時,調用了Animal 類中的 speak():

>>> animal_speak(Animal())

動物會說話...

傳遞Cat 的對象時,調用了Cat 類中的 speak():

>>> animal_speak(Cat())

喵喵...

傳遞Dog 的對象時,調用了Dog 類中的 speak():

>>> animal_speak(Dog())

汪汪...

傳遞Duck 的對象時,調用了Duck 類中的 speak():

>>> animal_speak(Duck())

嘎嘎...

可以看到,我們可以給animal_speak() 函數傳遞多種不同類型的對象,為animal_speak() 函數傳遞不同類型的參數,輸出了不同的結果,這就是多態。

5,鴨子類型

在靜態類型語言中,有嚴格的類型判斷,上面的animal_speak() 函數的參數只能傳遞Animal 及其子類的對象。

而Python 屬于動態類型語言,不會進行嚴格的類型判斷。

因此,我們不僅可以為animal_speak() 函數傳遞Animal 及其子類的對象,還可以傳遞其它與Animal 類毫不相關的類的對象,只要該類中有speak() 方法就行。

這種特性,在Python 中被叫做鴨子類型,意思就是,只要一個事物走起來像鴨子,叫起來像鴨子,那么它就是鴨子,即使它不是真正的鴨子。

從代碼上來說,只要一個類中有speak() 方法,那么就可以將該類的對象傳遞給animal_speak() 函數。

比如,有一個鼓類Drum,其中有一個函數speak():

class Drum(object):

def speak(self):

print('咚咚...')

那么,類Drum 的對象也可以傳遞給animal_speak() 函數,即使Drum 與Animal 類毫不相關:

>>> animal_speak(Drum())

咚咚...

從另一個角度來考慮,實際上Python 函數中的參數,并沒有標明參數的類型。在animal_speak() 函數中,我們只是將參數叫做了animal 而已,因此我們就認為animal_speak() 函數應該接受Animal 類及其子類的對象,其實這僅僅只是我們認為的而已。

計算機并不知道animal 的含義,如果我們將原來的animal_speak() 函數:

def animal_speak(animal):

animal.speak()

改寫成:

def animal_speak(a):

a.speak()

實際上,我們知道,這兩個函數并沒有任何區別。因此,參數a可以是任意的類型,只要a 中有speak() 方法就行。這就是Python 能夠表現出鴨子特性的原因。

(完。)

推薦閱讀:

歡迎關注作者公眾號,獲取更多技術干貨。

總結

以上是生活随笔為你收集整理的python继承和多态_Python 简明教程 --- 21,Python 继承与多态的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 少妇久久久久久 | 我要看免费毛片 | 欧美暧暧视频 | 国产超碰人人模人人爽人人添 | 少妇太紧太爽又黄又硬又爽 | www.插插| 庆余年三| av永久网站 | 国产精品国色综合久久 | 亚洲欧美日韩不卡 | 人人澡人人看 | 中文在线字幕观看 | 久久成人精品一区二区 | 麻豆成人久久精品一区二区三区 | 亚洲影院一区二区三区 | 国产福利一区二区视频 | 男人桶女人桶爽30分钟 | 午夜少妇| 国产在线播放一区二区 | 日韩草比 | 国产日韩欧美在线观看 | 欧洲亚洲自拍 | 夜色视频网 | 国产精品4区 | 宇都宫紫苑在线播放 | 久久国产毛片 | 看全色黄大色黄女片18 | 精品福利一区二区三区 | 中文字幕在线观看的网站 | www.日韩av | 99国产精品久久久久久久 | 国产乱淫av片免费看 | 精品国产一区二区三区日日嗨 | h片在线免费观看 | 中文字幕人成乱码熟女香港 | www.日韩视频 | 原神淫辱系列同人h | 国产一区二区三区免费播放 | av片在线观看网站 | 无码乱人伦一区二区亚洲 | 国产毛片久久久久久 | 欧美在线视频你懂的 | 91精品国自产在线偷拍蜜桃 | av观看网站| 欧美亚日韩 | 偷拍网亚洲 | 国产91精品久久久久久久 | 手机av免费 | 国产人妻人伦精品1国产丝袜 | 女人被男人躁得好爽免费视频 | 伦乱天堂 | 久久久久免费观看 | 青娱乐在线视频观看 | 亚洲一区二区播放 | 18岁成年人网站 | 亚洲黄网av | 久久久精品视频一区 | 一级视频在线观看 | 妺妺窝人体色www聚色窝仙踪 | 黄色片网站在线免费观看 | 超碰人人草人人干 | 视频这里只有精品 | 婷婷色影院 | 亚洲高潮无码久久 | 爽爽爽av | 超碰不卡| 蜜桃成熟时李丽珍国语 | 91在线亚洲 | 国产亚洲欧美日韩精品一区二区三区 | 亚洲国产综合网 | 国产不卡免费视频 | 日本a级片网站 | 亚洲精品国产精品国 | 无码一区二区三区 | 日本www视频在线观看 | 青青草91 | 欧美色图亚洲天堂 | 国产成人亚洲精品 | 九色一区| 伊人久久亚洲综合 | 国产日韩在线视频 | 成人免费在线 | 日韩最新av | 久久久久久久国产精品 | 激情综合文学 | 天天爱av| 超碰综合网| 麻豆va| 国产www | 毛片免费一区二区三区 | 亚洲自拍电影 | 俄罗斯av在线 | 久久国产精品电影 | 欧美日日日 | 综合久久久久综合 | 欧美网站免费 | 美女丝袜av| 欧美第1页| 黑人毛片网站 |