隨着abstract base classes,Python提供了一種方法來知道對象的行爲,而不用實際嘗試它。在標準庫中,我們爲collections.abc中的容器定義了一些ABCs。例如,一個可以測試的說法是迭代:在Python中,如何知道對象是否可以比較?
from collections.abc import Iterable
def function(argument):
if not isinstance(argument, Iterable):
raise TypeError('argument must be iterable.')
# do stuff with the argument
我希望會有一個這樣的ABC決定是否一個類的實例可以比擬的,但沒能找到。測試__lt__
方法的存在是不夠的。例如,字典無法比較,但__lt__
仍然定義(實際上與object
相同)。
>>> d1, d2 = {}, {}
>>> d1 < d2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: dict() < dict()
>>> hasattr(d1, '__lt__')
True
所以我的問題是:是否有一個簡單的方法來做到這一點,而不做比較自己和捕捉TypeError
?我的用例與已排序的容器類似:我想在插入第一個元素而不是等待第二個元素時引發異常。我想到了用元素本身相比,但有一個更好的方法:
def insert(self, element):
try:
element < element
except TypeError as e:
raise TypeError('element must be comparable.')
# do stuff
ABCs不僅說明了那裏的屬性。這就是他們可以執行的所有事情,但是由於他們是選擇性的(需要繼承或明確註冊),大多數ABC可以並且確實定義合同。當'isinstance(x,abc.Sized)'時,假設'x .__ len__'是一個返回非負整數的方法是比較合理的。當然,它不是通過編程來檢查的,但是Python的動態性和真實性一樣,什麼都不能檢查。 – delnan 2015-04-05 12:30:57
@delnan:當然,這是ABC的意圖。但由於比較方法的合同在傳遞不兼容的對象類型時返回'NotImplemented',因此您無法使用ABC測試該合同在該範圍內的執行情況。 – 2015-04-05 12:33:47
@匿名者:請不要添加該功能;調用所有比較方法會導致副作用,因爲自定義類可能會在調用其特殊方法時執行任何操作,包括更改其自己的狀態。 – 2015-04-05 12:36:16