2016-06-29 34 views
5

Sto cercando di capire cosa devono fare i dizionari Python internamente per individuare una chiave. Mi sembra che hash sarebbe stato valutato per primo, e se c'è una collisione, Python avrebbe iterato attraverso i tasti fino a trovare uno per cui eq restituisce True. Il che mi rende chiedo perché il seguente codice funziona (codice di prova solo per comprendere i meccanismi interni):Qual è l'ordine della valutazione __hash__ e __eq__ per un ditt di Python?

class MyClass(object): 
    def __eq__(self, other): 
     return False 

    def __hash__(self): 
     return 42 

if __name__=='__main__': 

    o1 = MyClass() 
    o2 = MyClass() 
    d = {o1: 'o1', o2: 'o2'} 
    assert(o1 in d)  # 1 
    assert(d[o1]=='o1') # 2 
    assert(o2 in d)  # 3 
    assert(d[o2]=='o2') # 4 

non dovrebbe il dizionario non essere in grado di trovare la chiave corretta (ritorno sia 'O1' o 'o2' in entrambi casi n. 2 e n. 4, o che generano un errore, a seconda dell'implementazione interna). In che modo è in grado di eseguire la chiave corretta in entrambi i casi, quando non dovrebbe mai essere in grado di "equare" correttamente le chiavi (poiché eq restituisce False).

Tutta la documentazione che ho visto su hashing cita sempre hash e eq insieme, mai cmp, ne ecc, che mi fa pensare questi 2 sono gli unici che hanno un ruolo in questa scenario.

risposta

5

Tutto ciò che si utilizza come tasto dict deve soddisfare l'invariante bool(x == x) is True. (Avrei appena detto x == x, ma ci sono oggetti ragionevoli per i quali non è nemmeno un booleano.)

Il dict presuppone che questo rimarrà, quindi la routine che utilizza per verificare l'uguaglianza della chiave verifica effettivamente l'identità dell'oggetto prima prima di utilizzare ==. Questo controllo preliminare è un dettaglio di implementazione; non dovresti contare sul fatto che ciò accada o non accada.

Oggetti ragionevoli per i quali (x == x) is not True includono float('nan') e numpy.array([1, 2]).

+0

quindi nel suo esempio o1 == o1 restituirebbe False, ma id (o1) == id (o1) restituire True? –

+0

Ho appena provato e o1 == o1 restituisce False e id (o1) == id (o1) restituisce True –

+0

@TimurRidjanovic: Sì. 'is' è un modo più sicuro e talvolta più efficiente per confrontare l'identità dell'oggetto, però. – user2357112

Problemi correlati