2016-05-31 10 views
5

Sto usando Python 3.5.1 e il nuovo analizzatore di tipo statico v10.4.1 MyPy v0.4.1.Perché la definizione dei tipi di argomento per __eq__ genera un errore di tipo MyPy?

ho qualche codice più complesso che ho ridotto fino a questo semplice classe Python possibile necessario per riprodurre l'errore:

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

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

Esecuzione del correttore tipo mypy test.py produce il seguente errore:

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

La mia teoria basata su these docs è che __eq__ e __neq__ sull'oggetto hanno tipi già definiti, che si scontrano con la ridefinizione di questi tipi della mia sottoclasse. La mia domanda è come definire questi tipi per assicurarmi che l'opzione __eq__ sia controllata con il tipo scelto.

risposta

4

== si suppone di prendere arbitrari altri oggetti, non solo oggetti del tipo. Se non riconosce l'altro oggetto, deve restituire NotImplemented:

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 

Inoltre, se hai bisogno di fare riferimento a MyObject per tipo suggerimenti all'interno del suo stesso corpo, è necessario utilizzare una stringa, 'MyObject' invece di MyObject . MyObject non esiste ancora.

+0

Re: riferendosi a 'MyObject' al suo interno il proprio corpo, l'ho già fatto altrove nel mio codice senza citare e ottengo nessun errore da MyPy: https://github.com/pirate/py-data/blob/ master/recursive_descent_parser.py # L78 –

+1

@NickSweeting: l'hai eseguito? [Si dovrebbe ottenere un errore quando si tenta di eseguirlo.] (Http://ideone.com/vk5VX6) – user2357112

+0

Ah, grazie @ user2357112, ho solo provato a mypy-it e ho dimenticato di eseguirlo. Il cambio su stringhe ha funzionato. –

2

La lettura dei documenti è corretta - è necessario fornire il metodo (__eq__) alla stessa firma già presente nella classe di base (object) oppure a uno più permissivo.

La ragione di ciò è che perché il vostro MyObject è un sottotipo di object, un MyObject potrebbe essere superato da nessuna parte che si aspetta un object ... il che significa che il codice potrebbe confrontare con qualsiasi altro object, e non c'è modo legittimo per il controllo del tipo di lamentarsi. Quindi, per rispecchiare questo, il tuo __eq__ deve essere scritto per aspettarsi un qualsiasi object.

Che cosa si può fare è proprio davanti nel corpo del metodo, verificare il tipo e il ritorno (o sollevare un'eccezione):

if not isinstance(other, MyObject): 
    return False 

Poi, come those docs say, Mypy è abbastanza intelligente che dopo tale controllo, essa saprete che other è un MyObject e trattarlo di conseguenza.

Problemi correlati