簡析 Python 的 `NotImplemented`
來自專欄極光日報
簡評:本文討論 Python 的
NotImplemented
它是什麼,它意味著什麼,什麼時候應該使用。
是什麼
>>> type(NotImplemented)<type NotImplementedType>
NotImplemented
是 Python 內置命名空間中的六個常量之一。其他還有 False
, True
, None
, Ellipsis
和 __debug__
。類似於 Ellipsis
,NotImplemented
可以重新賦值。 賦值給它,即使作為屬性名稱,也不會引發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 自定義類中的函數和運算符重載