Python抽象基類的定義與使用方法
前言:
我們寫Python基本不需要自己創(chuàng)建抽象基類,而是通過鴨子類型來解決大部分問題?!读鲿车腜ython》作者使用了15年Python,但只在項目中創(chuàng)建過一個抽象基類。我們更多時候是創(chuàng)建現(xiàn)有抽象基類的子類,或者使用現(xiàn)有的抽象基類注冊。本文的意義在于,了解抽象基類的定義與使用,可以幫助我們理解抽象基類是如何實現(xiàn)的,為我們以后學習后端語言(比如Java、Golang)打下基礎。畢竟抽象基類是編程語言通用設計。
1、定義抽象基類的子類
先回顧下什么是抽象基類:Python的抽象基類是指必須讓繼承它的子類去實現(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)
通過抽象基類collections.MutableSequence源碼:

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

Iterable、Container、Sized
這三個抽象基類是最基礎的類,各個集合都繼承了這三個抽象基類。
Itearble通過__iter__方法支持迭代Container通過__contains__方法支持in運算符Sized通過__len__方法支持len()函數(shù)
Sequence、Mapping、Set
不可變集合類型,各自都有可變的子類。
MappingView
.items() 、.keys() 、 .values()返回的對象分別是ItemsView、KeysView和ValuesView的實例。
Callable、Hashable
為內置函數(shù)isinstance提供支持,判斷對象能不能調用或散列。
Iterator
迭代器。
numbers
numbers的抽象基類有以下幾種:
NumberComplexRealRationalIntegral
這叫做數(shù)字塔,頂部是超類,底部是子類。比如使用isinstance(x, numbers.Integral)檢查一個數(shù)是不是整數(shù),這樣代碼就能接受int、bool(int的子類),再比如使用isinstance(x, numbers.Real)檢查浮點數(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
要點:
- 繼承
abc.ABC - 使用
@abc.abstractmethod裝飾器標記抽象方法 - 抽象基類也可以包含普通方法
- 抽象基類的子類必須覆蓋抽象方法(普通方法可以不覆蓋),可以使用super()函數(shù)調用抽象方法,為它添加功能,而不是從頭開始實現(xiàn)
4、再看白鵝類型
白鵝類型的定義有一點難以理解,如果理解了虛擬子類,就能加快理解白鵝類型。虛擬子類并不是抽象基類的真正子類,而是注冊到抽象基類上的子類,這樣Python就不會做強制檢查了。
注冊的方式有兩種:
- register方法
Python3.3以前只能使用register方法,比如collections.abc模塊的源碼中,把內置類型tuple、str、range和memoryview注冊為Sequence的虛擬子類:
Sequence.register(tuple) Sequence.register(str) Sequence.register(range) Sequence.register(memoryview)
- register裝飾器
把TomboList注冊為Tombola的虛擬子類:
@Tombola.register
class TomboList(list):
...
白鵝類型和鴨子類型是Python的動態(tài)特性,它們的共同點是,只要長的像,Python就不會做強制檢查,鴨子類型是針對普通類的子類而言的,白鵝類型是針對抽象基類的虛擬子類而言的。
參考資料:
《流暢的Python》第11章 接口:從協(xié)議到抽象基類
到此這篇關于Python抽象基類的定義與使用方法的文章就介紹到這了,更多相關Python抽象基類的定義與使用內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
python進程間數(shù)據(jù)交互的幾種實現(xiàn)方式
本文主要介紹了python進程數(shù)據(jù)交互的幾種實現(xiàn)方式,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-05-05
Python中json.dumps()和json.dump()的區(qū)別小結
在Python中,json.dumps()和json.dump()是兩個常用的函數(shù),本文主要介紹了Python中json.dumps()和json.dump()的區(qū)別小結,具有一定的參考價值,感興趣的可以了解一下2024-02-02
Python基于easygui實現(xiàn)pdf和word轉換小程序
這篇文章主要為大家詳細介紹了Python如何基于easygui實現(xiàn)pdf和word轉換小程序,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下2024-04-04
pandas?實現(xiàn)?in?和?not?in?的用法及使用心得
pandas按條件篩選數(shù)據(jù)時,除了使用query()方法,還可以使用isin和對isin取反進行條件篩選,今天通過本文給大家介紹pandas?實現(xiàn)?in?和?not?in?的用法及使用心得,感興趣的朋友跟隨小編一起看看吧2023-01-01
Python實現(xiàn)葵花8號衛(wèi)星數(shù)據(jù)自動下載實例
這篇文章主要為大家介紹了Python實現(xiàn)葵花8號衛(wèi)星數(shù)據(jù)自動下載實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-10-10
python實現(xiàn)將中文日期轉換為數(shù)字日期
這篇文章主要介紹了python實現(xiàn)將中文日期轉換為數(shù)字日期,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-07-07
詳解Python3.8+PyQt5+pyqt5-tools+Pycharm配置詳細教程
這篇文章主要介紹了Python3.8+PyQt5+pyqt5-tools+Pycharm配置詳細教程,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧2020-11-11

