python抽象基类的作用_Python:多态、鸭子模型和抽象基类
1. 多態(tài)
什么是多態(tài)
-- 多態(tài),指的是一種事務具有多種形態(tài);
-- python是一種動態(tài)語言,默認支持多態(tài),同一個方法 調(diào)用 不同的類對象 ,執(zhí)行的 結(jié)果各不相同;
多態(tài)實現(xiàn)
-- 繼承:不同子類 繼承 同一父類;
-- 重寫:子類重寫 同一個方法,保證執(zhí)行結(jié)果各不相同;
示例
-- 有如下代碼:
>>> class Animals():
... def talk(self):
... print("Animal talk")
...
>>>
>>> class People(Animals): # 繼承 Animals 類
... def talk(self):
... print('People speak language')
...
>>>
>>> class Cat(Animals): # 繼承 Animals 類
... def talk(self):
... print('Cat say miaomiao')
...
>>>
>>> cat = Cat()
>>> peo = People()
>>>
>>> cat.talk() # 調(diào)用 talk 方法
Cat say miaomiao
>>> peo.talk() # 調(diào)用 talk 方法
People speak language
如上所示:
-- cat 和 peo 兩個對象調(diào)用同一個 talk() 方法;
-- 最后得到兩種不同的結(jié)果;
多態(tài)的優(yōu)點:
-- 多態(tài)可以增加代碼的靈活度;
-- 是調(diào)用方法的技巧,不會影響到類的內(nèi)部設計;
-- 多態(tài)可以看做 接口函數(shù)的重用,同一種接口方法 通過 接收不同的類 對象,從而實現(xiàn)不同的功能;
多態(tài)使用場景:
-- 方法參數(shù)接收同一父類的不同子類對象。
2. 鴨子模型
什么是鴨子模型
-- 當看到一只鳥走起來像鴨子,游泳起來也像鴨子,叫起來也像鴨子,那么這只鳥就可以被稱為鴨子;
-- 鴨子模型和多態(tài)一樣,都是接受不同的類對象,并調(diào)用相同的方法(即:鴨子的 游泳 和 叫 方法);
-- 對于一個鴨子模型來說,我們并 不關心接收的類對象是否真的是鴨子類,只關心這個類是如何被使用的;
-- 注意:如果這些需要被調(diào)用的方法不存在,那么將引發(fā)一個運行時錯誤。
示例
-- 有如下代碼:
>>> class Duck:
... def quack(self):
... print("duck quack")
...
>>>
>>> class Bird: # Bird 類與 Duck 類無繼承關系
... def quack(self):
... print("bird quack")
...
>>>
>>> class Dog: # Dog類與 Duck 類無繼承關系
... def quack(self):
... print("dog quack")
...
>>>
>>> def animal_quack(animal): # animal_quack 方法可以調(diào)用任何對象的 quack() 方法,不關心對象是誰
... animal.quack()
...
>>>
>>> duck = Duck()
>>> bird = Bird() # bird 實例與 duck 實例無任何關系
>>> dog = Dog() # dog 實例與 duck 實例無任何關系
>>>
>>> for animal in [duck, bird, dog]:
... animal_quack(animal)
...
duck quack
bird quack
dog quack
-- 如上所示:
-- duck、bird、dog 分別來自三個不同的類,而且類之間是 沒有繼承關系 的;
-- duck、bird、dog 調(diào)用 animal_quack 方法,得到三種不同的結(jié)果,符合多態(tài)的特征;
鴨子模型的優(yōu)點:
-- 鴨子模型不關關心類對象是什么,不需要類之間具有繼承關系;
-- 鴨子模型讓代碼比多態(tài)更加靈活度;
多態(tài)使用場景:
-- 鴨子模型中,接收不同的類將會產(chǎn)生不同的行為,而無須明確知道這個類實際上是什么,這是多態(tài)的重要應用場景;
-- 實際生產(chǎn)環(huán)境中,主要用于 接口開發(fā),即用同一個函數(shù)接收不同的類對象,從而實現(xiàn)不同的功能,而且無需關注對象之間的繼承關系;
3. 抽象基類
什么是抽象基類
-- 抽象基類,這個詞可能聽著比較"深奧",其實 抽象 就是 假 的意思,基類 就是 父類,抽象基類 就是 假父類;
-- 具體來說,由 abc.ABCMeta 這個元類實現(xiàn)的類,就是抽象基類;
示例:
-- 如下代碼中的 AbstractClass 類繼承自 abc.ABCMeta,AbstractClass 就是抽象基類;
class AbstractClass(metaclass=abc.ABCMeta):
pass
抽象基類的作用
-- 判斷是否為某個對象的實例
>>> class MyList(object):
... def __init__(self, my_list):
... self.my_list= my_list
... def __len__(self):
... return len(self.my_list)
...
>>>
>>> class NewList(MyList): # NewList 繼承自 MyList
... pass
...
>>> ml = MyList(["a", "b", "c"])
>>>
>>> from collections.abc import Sized, Iterable
>>>
>>> print(isinstance(ml, Sized))
True # 返回 True,因為這里會檢查實例對象中有沒有__len__方法,有即輸出True
>>> nl = NewList([1, 2, 3])
>>> print(isinstance(nl, MyList))
True # 返回 True,因為 nl 實例化的類 NewList 同時也是 MyList 的子類
-- 強制要求父類被子類繼承,并在子類實現(xiàn)某個方法,否則子類初始化時就會報錯;
>>> from abc import ABCMeta,abstractmethod
>>>
>>>
>>> class Source(metaclass=ABCMeta): # 創(chuàng)建抽象基類 Source
... @abstractmethod # 表示裝飾的方法必須被子類所實現(xiàn),否則會報錯
... def get(self,key):
... pass
...
>>>
>>> class Mysource(Source): # 子類 Mysource 繼承自 抽象基類 Source
... def get(self,key): # 實現(xiàn) get 方法,這個方法是 抽象基類 Source 強制要求實現(xiàn)的
... pass
...
>>>
>>> class Mysource1(Source): # 子類 Mysource1 沒有實現(xiàn) 抽象基類 Source 強制要求實現(xiàn)的 get 方法
... pass
...
>>> test = Source() # test 直接實例化 Source 父類
Traceback (most recent call last): # 此處報錯,因為抽象類無法實現(xiàn)實例化
File "", line 1, in
TypeError: Can't instantiate abstract class Source with abstract methods get
>>>
>>> test = Mysource() # 此處實例化 Mysource,未報錯
>>>
>>> test = Mysource1()
Traceback (most recent call last): # 報錯,繼承類必須實現(xiàn)抽象類的方法
File "", line 1, in
TypeError: Can't instantiate abstract class Mysource1 with abstract methods get
抽象基類使用場景
-- 接口強制規(guī)定,主要是 強制子類實現(xiàn)某個方法,否則就提示報錯;
抽象基類的有點:
-- 處理繼承問題方面更加規(guī)范、系統(tǒng);
-- 明確調(diào)用之間的相互關系,使得繼承層次更加清晰;
抽象基類的缺點:
-- 抽象基類在 python 并非在于用來繼承,主要用來理解 python繼承 的定義,應該 盡量使用鴨子模型;
-- 如果一定要繼承接口的話,比較 推薦多繼承,抽象基類容易 設計過度;
總結(jié)
以上是生活随笔為你收集整理的python抽象基类的作用_Python:多态、鸭子模型和抽象基类的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Django模型
- 下一篇: Flask简介与简单项目操作流程