簡體   English   中英

mypy:“ __eq__”與超類型“ object”不兼容

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM