2016-06-29 15 views
5

Próbuję zrozumieć, co słowniki Pythona muszą robić wewnętrznie, aby zlokalizować klucz. Wydaje mi się, że najpierw zostanie oszacowany hash, a jeśli dojdzie do kolizji, Python będzie iterować przez klawisze, dopóki nie znajdzie takiego, dla którego eq zwraca True. Co sprawia, że ​​zastanawiam się, dlaczego następujący kod działa (kod testowy tylko dla zrozumienia wewnętrzne):Jaka jest kolejność oceny __hash__ i __eq__ dla dict Pythona?

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 

Gdyby nie słownika być w stanie znaleźć właściwego klucza (powrót albo o1 „” lub „” w obu O2 w przypadkach # 2 i # 4 lub zgłaszając błąd, w zależności od implementacji wewnętrznej). W jaki sposób jest on w stanie wylądować na właściwym kluczu w obu przypadkach, kiedy nigdy nie będzie w stanie poprawnie "zrównać" kluczy (ponieważ eq zwraca False).

Cała dokumentacja Widziałem na mieszania zawsze wspomina hash i eq razem, nigdy cmp, ne etc, które kojarzy mi się te 2 są jedynymi, które odgrywają rolę w tym scenariusz.

Odpowiedz

5

Wszystko, co używasz jako klucza dyktującego, musi spełniać niezmiennik, który jest bool(x == x) is True. (Powiedziałbym tylko, że są to uzasadnione obiekty, dla których nie jest to nawet boolean.)

Dykt zakłada, że ​​to się utrzyma, więc procedura, której używa do sprawdzenia równości klucza, faktycznie sprawdza najpierw tożsamość obiektu przed użyciem ==. Ta wstępna kontrola jest szczegółem wdrożenia; nie powinieneś polegać na tym, co się dzieje lub nie.

Rozsądne obiekty, dla których (x == x) is not True obejmują float('nan') i numpy.array([1, 2]).

+0

tak w swoim przykładzie o1 == o1 zwróci False, ale id (o1) == id (o1) zwróci True? –

+0

Po prostu wypróbowałem i o1 == o1 zwraca False i id (o1) == id (o1) zwraca True –

+0

@TimurRidjanovic: Tak. 'is' jest bezpieczniejszym, a czasami bardziej wydajnym sposobem porównywania tożsamości obiektu. – user2357112

Powiązane problemy