2016-05-31 4 views
5

Ich verwende Python 3.5.1 und den neu veröffentlichten MyPy v0.4.1 statischen Typ-Analysator.Warum verursacht das Definieren der Argumenttypen für __eq__ einen MyPy-Typfehler?

Ich habe etwas komplexeren Code, den ich habe auf diese möglichst einfache Python-Klasse reduziere nach unten erforderlich, um den Fehler zu reproduzieren:

class MyObject(object): 
    def __init__(self, value: int=5) -> None: 
     self.value = value 

    def __eq__(self, other: MyObject) -> bool: 
     return self.value == other.value 

Ausführen des Typprüfers mypy test.py die folgenden Fehler erzeugt:

test.py: note: In class "MyObject": 
test.py:5: error: Argument 1 of "__eq__" incompatible with supertype "object" 

Meine Theorie basierend auf these docs ist, dass __eq__ und __neq__ auf Objekt Typen bereits definiert haben, die mit der Neudefinition dieser Typen meiner Unterklasse kollidieren. Meine Frage ist, wie ich diese Typen definiere, um sicherzustellen, dass __eq__ mit meinem gewählten Typ typgeprüft ist.

Antwort

4

== soll beliebige andere Objekte nehmen, nicht nur Objekte Ihrer Art. Wenn es nicht das andere Objekt nicht erkennt, sollte es NotImplemented zurück:

class MyObject(object): 
    def __init__(self, value: int=5) -> None: 
     self.value = value 

    def __eq__(self, other: object) -> bool: 
     if not isinstance(other, MyObject): 
      return NotImplemented 
     return self.value == other.value 

Auch, wenn Sie auf MyObject für Typ Hinweise in seinem eigenen Körper beziehen müssen, müssen Sie eine Zeichenfolge verwenden, 'MyObject' statt MyObject . MyObject existiert noch nicht.

+0

Re: Bezug auf 'MyObject' im Inneren des eigenen Körpers, ich habe ohne Angabe in meinem Code, dass an anderer Stelle getan und ich bekomme keine Fehler von MyPy: https://github.com/pirate/py-data/blob/ master/recursive_descent_parser.py # L78 –

+1

@NickSweeting: Hast du es ausgeführt? [Sie sollten eine Fehlermeldung erhalten, wenn Sie versuchen, es zu laufen.] (Http://ideone.com/vk5VX6) – user2357112

+0

Ah, danke @ user2357112, ich mypy-ing es nur versucht, und vernachlässigt es eigentlich laufen. Es wurde in Strings umgewandelt. –

2

Ihr Lesen der Dokumente ist richtig - Sie müssen die Methode (__eq__) die gleiche Signatur wie es bereits in der Basisklasse (object) hat, oder sonst eine permissive geben.

Der Grund dafür ist, dass, weil Ihr MyObject ein Subtyp von object ist, ein MyObject überall weitergegeben werden kann, die ein object erwartet ... was bedeutet, dass dieser Code es mit jeder anderen object vergleichen konnte, und es gibt keine legitime Art und Weise für den Typ Checker zu beschweren. Also, um zu reflektieren, dass Ihr __eq__ hat geschrieben werden, die mit object zu erwarten.

Was Sie tun können, ganz vorne im Körper des Verfahrens ist, überprüfen Sie die Art und zurück (oder eine Ausnahme auslösen):

if not isinstance(other, MyObject): 
    return False 

Dann als those docs say ist Mypy klug genug, dass nach dieser Kontrolle, es Werde wissen, dass other ein MyObject ist und behandle es dementsprechend.

Verwandte Themen