人妖在线一区,国产日韩欧美一区二区综合在线,国产啪精品视频网站免费,欧美内射深插日本少妇

新聞動態(tài)

Python抽象基類的定義與使用方法

發(fā)布日期:2021-12-23 18:31 | 文章來源:源碼中國

我們寫Python基本不需要自己創(chuàng)建抽象基類,而是通過鴨子類型來解決大部分問題。《流暢的Python》作者使用了15年Python,但只在項目中創(chuàng)建過一個抽象基類。我們更多時候是創(chuàng)建現(xiàn)有抽象基類的子類,或者使用現(xiàn)有的抽象基類注冊。本文的意義在于,了解抽象基類的定義與使用,可以幫助我們理解抽象基類是如何實現(xiàn)的,為我們以后學(xué)習(xí)后端語言(比如Java、Golang)打下基礎(chǔ)。畢竟抽象基類是編程語言通用設(shè)計。

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、extendpop等,則可以直接繼承無需實現(xiàn)。

注意:Python只會在運行時實例化FrenchDeck2類時真正檢查抽象方法的實現(xiàn),如果未實現(xiàn)會拋出TypeError異常,提示Can't instantiate abstract class之類的。

2、標(biāo)準(zhǔn)庫中的抽象基類

為了知道哪些抽象基類可以使用,我們可以看看標(biāo)準(zhǔn)庫。

collections.abc

collections.abc的抽象基類如下圖所示:

Iterable、Container、Sized

這三個抽象基類是最基礎(chǔ)的類,各個集合都繼承了這三個抽象基類。

  • Itearble通過__iter__方法支持迭代
  • Container通過__contains__方法支持in運算符
  • Sized通過__len__方法支持len()函數(shù)

Sequence、Mapping、Set

不可變集合類型,各自都有可變的子類。

MappingView

.items() 、.keys() 、 .values()返回的對象分別是ItemsView、KeysViewValuesView的實例。

Callable、Hashable

為內(nèi)置函數(shù)isinstance提供支持,判斷對象能不能調(diào)用或散列。

Iterator

迭代器。

numbers

numbers的抽象基類有以下幾種:

  • Number
  • Complex
  • Real
  • Rational
  • Integral

這叫做數(shù)字塔,頂部是超類,底部是子類。比如使用isinstance(x, numbers.Integral)檢查一個數(shù)是不是整數(shù),這樣代碼就能接受int、bool(int的子類),再比如使用isinstance(x, numbers.Real)檢查浮點數(shù),這樣代碼就能接受bool、intfloat、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裝飾器標(biāo)記抽象方法
  • 抽象基類也可以包含普通方法
  • 抽象基類的子類必須覆蓋抽象方法(普通方法可以不覆蓋),可以使用super()函數(shù)調(diào)用抽象方法,為它添加功能,而不是從頭開始實現(xiàn)

4、再看白鵝類型

白鵝類型的定義有一點難以理解,如果理解了虛擬子類,就能加快理解白鵝類型。虛擬子類并不是抽象基類的真正子類,而是注冊到抽象基類上的子類,這樣Python就不會做強制檢查了。

注冊的方式有兩種:

  • register方法

Python3.3以前只能使用register方法,比如collections.abc模塊的源碼中,把內(nèi)置類型tuple、str、rangememoryview注冊為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é)議到抽象基類

到此這篇關(guān)于Python抽象基類的定義與使用方法的文章就介紹到這了,更多相關(guān)Python抽象基類的定義與使用內(nèi)容請搜索本站以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持本站!

版權(quán)聲明:本站文章來源標(biāo)注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請保持原文完整并注明來源及原文鏈接。禁止復(fù)制或仿造本網(wǎng)站,禁止在非www.sddonglingsh.com所屬的服務(wù)器上建立鏡像,否則將依法追究法律責(zé)任。本站部分內(nèi)容來源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來,僅供學(xué)習(xí)參考,不代表本站立場,如有內(nèi)容涉嫌侵權(quán),請聯(lián)系alex-e#qq.com處理。

相關(guān)文章

實時開通

自選配置、實時開通

免備案

全球線路精選!

全天候客戶服務(wù)

7x24全年不間斷在線

專屬顧問服務(wù)

1對1客戶咨詢顧問

在線
客服

在線客服:7*24小時在線

客服
熱線

400-630-3752
7*24小時客服服務(wù)熱線

關(guān)注
微信

關(guān)注官方微信
頂部