Python抽象基類的定義與使用方法
前言:
我們寫(xiě)Python基本不需要自己創(chuàng)建抽象基類,而是通過(guò)鴨子類型來(lái)解決大部分問(wèn)題?!读鲿车腜ython》作者使用了15年Python,但只在項(xiàng)目中創(chuàng)建過(guò)一個(gè)抽象基類。我們更多時(shí)候是創(chuàng)建現(xiàn)有抽象基類的子類,或者使用現(xiàn)有的抽象基類注冊(cè)。本文的意義在于,了解抽象基類的定義與使用,可以幫助我們理解抽象基類是如何實(shí)現(xiàn)的,為我們以后學(xué)習(xí)后端語(yǔ)言(比如Java、Golang)打下基礎(chǔ)。畢竟抽象基類是編程語(yǔ)言通用設(shè)計(jì)。
1、定義抽象基類的子類
先回顧下什么是抽象基類:Python的抽象基類是指必須讓繼承它的子類去實(shí)現(xiàn)它所要求的抽象方法的類。
如下代碼定義了抽象基類collections.MutableSequence的子類:
import collections
Card = collections.namedtuple('Card', ['rank', 'suit'])
class FrenchDeck2(collections.MutableSequence):
ranks = [str(n) for n in range(2, 11)] + list('JQKA')
suits = 'spades diamonds clubs hearts'.split()
def __init__(self):
self._cards = [Card(rank, suit) for suit in self.suits
for rank in self.ranks]
def __len__(self):
return len(self._cards)
def __getitem__(self, position):
return self._cards[position]
def __setitem__(self, position, value): # <1>
self._cards[position] = value
def __delitem__(self, position): # <2>
del self._cards[position]
def insert(self, position, value): # <3>
self._cards.insert(position, value)
通過(guò)抽象基類collections.MutableSequence源碼:

可以發(fā)現(xiàn),它有三個(gè)抽象方法__setitem__ 、 __delitem__ 、insert,所以FrenchDeck2類必須實(shí)現(xiàn)它們。而對(duì)于其他非抽象方法比如append、extend、pop等,則可以直接繼承無(wú)需實(shí)現(xiàn)。
注意:Python只會(huì)在運(yùn)行時(shí)實(shí)例化FrenchDeck2類時(shí)真正檢查抽象方法的實(shí)現(xiàn),如果未實(shí)現(xiàn)會(huì)拋出TypeError異常,提示Can't instantiate abstract class之類的。
2、標(biāo)準(zhǔn)庫(kù)中的抽象基類
為了知道哪些抽象基類可以使用,我們可以看看標(biāo)準(zhǔn)庫(kù)。
collections.abc
collections.abc的抽象基類如下圖所示:

Iterable、Container、Sized
這三個(gè)抽象基類是最基礎(chǔ)的類,各個(gè)集合都繼承了這三個(gè)抽象基類。
Itearble通過(guò)__iter__方法支持迭代Container通過(guò)__contains__方法支持in運(yùn)算符Sized通過(guò)__len__方法支持len()函數(shù)
Sequence、Mapping、Set
不可變集合類型,各自都有可變的子類。
MappingView
.items() 、.keys() 、 .values()返回的對(duì)象分別是ItemsView、KeysView和ValuesView的實(shí)例。
Callable、Hashable
為內(nèi)置函數(shù)isinstance提供支持,判斷對(duì)象能不能調(diào)用或散列。
Iterator
迭代器。
numbers
numbers的抽象基類有以下幾種:
NumberComplexRealRationalIntegral
這叫做數(shù)字塔,頂部是超類,底部是子類。比如使用isinstance(x, numbers.Integral)檢查一個(gè)數(shù)是不是整數(shù),這樣代碼就能接受int、bool(int的子類),再比如使用isinstance(x, numbers.Real)檢查浮點(diǎn)數(shù),這樣代碼就能接受bool、int、float、fractions.Fraction。
3、定義抽象基類
抽象基類的示例代碼如下:
# BEGIN TOMBOLA_ABC
import abc
class Tombola(abc.ABC): # <1>
@abc.abstractmethod
def load(self, iterable): # <2>
"""Add items from an iterable."""
@abc.abstractmethod
def pick(self): # <3>
"""Remove item at random, returning it.
This method should raise `LookupError` when the instance is empty.
"""
def loaded(self): # <4>
"""Return `True` if there's at least 1 item, `False` otherwise."""
return bool(self.inspect()) # <5>
def inspect(self):
"""Return a sorted tuple with the items currently inside."""
items = []
while True: # <6>
try:
items.append(self.pick())
except LookupError:
break
self.load(items) # <7>
return tuple(sorted(items))
# END TOMBOLA_ABC
要點(diǎn):
- 繼承
abc.ABC - 使用
@abc.abstractmethod裝飾器標(biāo)記抽象方法 - 抽象基類也可以包含普通方法
- 抽象基類的子類必須覆蓋抽象方法(普通方法可以不覆蓋),可以使用super()函數(shù)調(diào)用抽象方法,為它添加功能,而不是從頭開(kāi)始實(shí)現(xiàn)
4、再看白鵝類型
白鵝類型的定義有一點(diǎn)難以理解,如果理解了虛擬子類,就能加快理解白鵝類型。虛擬子類并不是抽象基類的真正子類,而是注冊(cè)到抽象基類上的子類,這樣Python就不會(huì)做強(qiáng)制檢查了。
注冊(cè)的方式有兩種:
- register方法
Python3.3以前只能使用register方法,比如collections.abc模塊的源碼中,把內(nèi)置類型tuple、str、range和memoryview注冊(cè)為Sequence的虛擬子類:
Sequence.register(tuple) Sequence.register(str) Sequence.register(range) Sequence.register(memoryview)
- register裝飾器
把TomboList注冊(cè)為Tombola的虛擬子類:
@Tombola.register
class TomboList(list):
...
白鵝類型和鴨子類型是Python的動(dòng)態(tài)特性,它們的共同點(diǎn)是,只要長(zhǎng)的像,Python就不會(huì)做強(qiáng)制檢查,鴨子類型是針對(duì)普通類的子類而言的,白鵝類型是針對(duì)抽象基類的虛擬子類而言的。
參考資料:
《流暢的Python》第11章 接口:從協(xié)議到抽象基類
到此這篇關(guān)于Python抽象基類的定義與使用方法的文章就介紹到這了,更多相關(guān)Python抽象基類的定義與使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python進(jìn)程間數(shù)據(jù)交互的幾種實(shí)現(xiàn)方式
本文主要介紹了python進(jìn)程數(shù)據(jù)交互的幾種實(shí)現(xiàn)方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05
Python中json.dumps()和json.dump()的區(qū)別小結(jié)
在Python中,json.dumps()和json.dump()是兩個(gè)常用的函數(shù),本文主要介紹了Python中json.dumps()和json.dump()的區(qū)別小結(jié),具有一定的參考價(jià)值,感興趣的可以了解一下2024-02-02
Python基于easygui實(shí)現(xiàn)pdf和word轉(zhuǎn)換小程序
這篇文章主要為大家詳細(xì)介紹了Python如何基于easygui實(shí)現(xiàn)pdf和word轉(zhuǎn)換小程序,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-04-04
pandas?實(shí)現(xiàn)?in?和?not?in?的用法及使用心得
pandas按條件篩選數(shù)據(jù)時(shí),除了使用query()方法,還可以使用isin和對(duì)isin取反進(jìn)行條件篩選,今天通過(guò)本文給大家介紹pandas?實(shí)現(xiàn)?in?和?not?in?的用法及使用心得,感興趣的朋友跟隨小編一起看看吧2023-01-01
Python實(shí)現(xiàn)葵花8號(hào)衛(wèi)星數(shù)據(jù)自動(dòng)下載實(shí)例
這篇文章主要為大家介紹了Python實(shí)現(xiàn)葵花8號(hào)衛(wèi)星數(shù)據(jù)自動(dòng)下載實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10
關(guān)于tensorflow的幾種參數(shù)初始化方法小結(jié)
今天小編就為大家分享一篇關(guān)于tensorflow的幾種參數(shù)初始化方法小結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-01-01
python實(shí)現(xiàn)將中文日期轉(zhuǎn)換為數(shù)字日期
這篇文章主要介紹了python實(shí)現(xiàn)將中文日期轉(zhuǎn)換為數(shù)字日期,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07
詳解Python3.8+PyQt5+pyqt5-tools+Pycharm配置詳細(xì)教程
這篇文章主要介紹了Python3.8+PyQt5+pyqt5-tools+Pycharm配置詳細(xì)教程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2020-11-11

