[英]mypy: “__eq__” incompatible with supertype “object”
這是我的代碼:
class Person:
def __init__(self, id):
self.id = id
def __eq__(self, other: 'Person') -> bool:
return self.id == other.id
def compare(self, other: 'Person') -> bool:
return self.id == other.id
mypy throw error: Argument 1 of "__eq__" incompatible with supertype "object"
__ eq__ error: Argument 1 of "__eq__" incompatible with supertype "object"
。
但是,如果我刪除__eq__
方法,盡管compare
與__eq__
相同,但mypy不會抱怨它,該怎么辦?
根本問題是__eq__
方法應該接受任何對象: my_object == 3
在運行時是合法的,並且應始終返回False。 您可以通過檢查基線類型定義親自了解該object
在Typeshed :簽名__eq__
是作為def __eq__(self, o: object) -> bool: ...
因此,為了使這項工作有效,實現__eq__
的正確方法是執行以下操作:
def __eq__(self, other: object) -> bool:
if not isinstance(other, Person):
# If we return NotImplemented, Python will automatically try
# running other.__eq__(self), in case 'other' knows what to do with
# Person objects.
return NotImplemented
return self.id == other.id
實際上,如果您更新了所使用的mypy版本,它將打印出一條注釋,建議您以這種方式構造代碼。
但是,這種方法的問題在於,如果您像Person() == 3
這樣愚蠢的事情,mypy現在將不再抱怨。 從技術上講,這應該返回布爾值,但是從實用上來說,如果您將一個person對象與一個int進行比較,您的代碼可能存在一個錯誤。
值得慶幸的是,mypy最近獲得了可以標記以下類型錯誤的功能:-- --strict-equality
。 現在,當您使用該標志運行mypy時,即使您定義__eq__
,執行Person() == 3
也會使mypy輸出錯誤,例如Non-overlapping equality check (left operand type: "Person", right operand type: "int")
以上述方式。
請注意,您需要使用master上最新版本的mypy才能使用此標志,直到發布下一版本的mypy(0.680)。 在撰寫本文時,大約應在2至3周內完成。
如果由於上述原因無法以上述方式定義__eq__
,我個人建議您抑制類型錯誤,而不要用Any
代替Person。
所以基本上,這樣做:
def __eq__(self, other: 'Person') -> bool: # type: ignore
return self.id == other.id
...也許還有關於為什么要抑制該錯誤的簡短說明。
這里的基本原理是嚴格地說__eq__
定義是不安全的(它違反了稱為Liskov替換原理的東西),並且,如果您需要做一些不安全的事情,最好顯式地標記您正在顛覆類型系統然后使用Any隱藏它。
至少通過這種方式,您仍然可以使Person() == 3
之類的表達式成為類型錯誤-如果使用Any
,例如Person() == 3
類的表達式將自動進行類型檢查。 到那時,您還可以只使用object
和結構化代碼來正確運行。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.