簡析 Python 的 `NotImplemented`

簡析 Python 的 `NotImplemented`

來自專欄極光日報

簡評:本文討論 Python 的 NotImplemented它是什麼,它意味著什麼,什麼時候應該使用。

是什麼

>>> type(NotImplemented)<type NotImplementedType>

NotImplemented是 Python 內置命名空間中的六個常量之一。其他還有 False, True, None, Ellipsis__debug__。類似於 EllipsisNotImplemented可以重新賦值。 賦值給它,即使作為屬性名稱,也不會引發SyntaxError異常,所以它不是真正的「真實(real/true)」的常量。當然,我們永遠都不應該重新賦值它。 但是,為了完整:

>>> None = hello...SyntaxError: cant assign to keyword>>> NotImplementedNotImplemented>>> NotImplemented = do not>>> NotImplementeddo not

意味著什麼,什麼時候用

NotImplemented是 python 特殊二元方法(例如__eq__(), __lt__(), __add__(), __rsub__())返回的特殊值,表示該操作沒有針對其他類型實現。而且,它轉換成 bool 類型表示 true

>>> bool(NotImplemented)True

可能會有這樣的疑問「應該在操作沒有實現時拋出NotImpementedError異常」,通過一些例子,我們將看到為什麼在實現二元特殊方法時不應該這樣。

讓我們通過為兩個非常基本的(但無用的)類 A 和 B 編寫一個 __eq__來展示NotImplemented常量的使用。[對於這個簡單的例子,為避免分心不實現__ne__()。但通常來說,除非有充分的理由,否則每次實現__eq__(),也應該實現__ne__()。]

# example.pyclass A(object): def __init__(self, value): self.value = value def __eq__(self, other): if isinstance(other, A): print(Comparing an A with an A) return other.value == self.value if isinstance(other, B): print(Comparing an A with a B) return other.value == self.value print(Could not compare A with the other class) return NotImplementedclass B(object): def __init__(self, value): self.value = value def __eq__(self, other): if isinstance(other, B): print(Comparing a B with another B) return other.value == self.value print(Could not compare B with the other class) return NotImplemented

現在在 interpreter 中:

>>> from example import A, B>>> a1 = A(1)>>> b1 = B(1)

現在我們可以嘗試對__eq __() 的不同調用並查看會發生什麼。提醒一下,在 Python 中,a == b實際上是調用 a.__eq__(b)

>>> a1 == a1Comparing an A with an ATrue

如預期的那樣,a1 等於 a1(本身),A 類中的__eq __() 方法處理此操作。將 b1 與自身進行比較也會得出類似的結果:

>>> b1 == b1Comparing a B with another BTrue

如果我們現在比較 a1 和 b1,會怎麼樣?由於 A 的__eq __()會檢查 other 參數是不是 B 的實例,我們期望 a1 .__ eq __(b1)處理比較操作並返回 True:

>>> a1 == b1Comparing an A with a BTrue

現在,如果我們將 b1 與 a1 進行比較(即調用 b1.__eq__(a1)),我們應該期望返回NotImplemented。這是因為 B 的__eq __()僅與其他 B 的實例進行比較。讓我們看看發生了什麼:

>>> b1 == a1Could not compare B against the other classComparing an A with a BTrue

b1 .__ eq __(a1)方法返回 NotImplemented導致 A 的__eq __()方法被調用,並且由於在 A 的__eq __()中定義了 A 和 B 之間的比較,我們得到了正確的結果(True)。

這就是返回 NotImplemented所做的事情。NotImplemented告訴運行時它應該請求 other 來滿足操作。 在表達式b1 == a1中,b1 .__ eq __(a1)返回 NotImplemented,它告訴 Python 嘗試調用 a1 .__ eq __(b1)。 由於 a1 足夠知道返回 True,所以表達式可以成功。 如果 A 的__eq __()也返回NotImplemented,那麼運行時將回退到基於對象標識(在 CPython 中是對象在內存中的地址)的相等內置行為。

注意,當b1 .__ eq __(a1)失敗時拋出一個NotImpementedError異常會突破代碼調用,除非被捕獲,但 NotImplemented不會被拋出並可以用於進一步的測試。

原文:Python』s `NotImplemented` Type

擴展閱讀:

  • Python 3.7 將引入 dataclass 裝飾器
  • Flask 發布 1.0 穩定版
  • 使用 Python 和 Click 編寫命令行應用程序
  • Python:range 對象並不是迭代器
  • PyPI 終於支持 Markdown 了

極光日報,極光開發者旗下媒體。

每天導讀三篇英文技術文章。

推薦閱讀:

條件語句
Nginx、Gunicorn在伺服器中分別起什麼作用?
Python安全編碼 — 代碼注入的實踐與防範
轉行AI之學習方法
Python 自定義類中的函數和運算符重載

TAG:Python | 編程語言 |