2015-03-24 82 views
26

Powiedzmy mam słownika:Dlaczego nie mogę wywołać metody hash() na pozornie nieosiągalnej metodzie nieusuwalnej instancji?

>>> d = {} 

Ma metodę clear():

>>> d.clear 
<built-in method clear of dict object at 0x7f209051c988> 

... który ma __hash__ atrybut:

>>> d.clear.__hash__ 
<method-wrapper '__hash__' of builtin_function_or_method object at 0x7f2090456288> 

... co jest na żądanie:

>>> callable(d.clear.__hash__) 
True 

Dlaczego więc nie mogę tego zrobić?

>>> hash(d.clear) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: unhashable type: 'dict' 

Uwaga: wiem, że dict obiekty są unhashable - Jestem ciekaw, dlaczego to ograniczenie rozciąga się na ich metodach, choć, jak wspomniano wyżej, pojawiają się one twierdzić inaczej?

Odpowiedz

33

Jest to metoda związana, a metody powiązane odnoszą się do self, np. słownik. To sprawia, że ​​metoda nie jest stała.

Ty może hash niezwiązana dict.clear metoda:

>>> d = {} 
>>> d.clear.__self__ 
{} 
>>> d.clear.__self__ is d 
True 
>>> hash(d.clear) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: unhashable type: 'dict' 
>>> hash(dict.clear) 
-9223372036586189204 

Metod na przypadkach, które hashable sami będą hashable, więc typ obiektu dla wbudowanej metod związanych implementuje metodę __hash__ ale podwyżki TypeError, gdy atrybut __self__ nie jest zgodny z formatem. Jest to zgodne z dokumentacją metody object.__hash__; Jeśli możesz ustawić go na None lub nie wdrożyć go wcale, to jest to lepsze, ale w tych przypadkach, w których haszowanie jest znane tylko podczas uruchamiania, jedyną dostępną opcją jest TypeError.

11

Martijn ma rację, jak to często bywa. Jeśli masz dict podklasę, która implementuje metodę __hash__, nawet metody bound stać hashable

class MyHashableDict(dict): 
    def __hash__(self): 
     return 42 

x = MyHashableDict() 
print(x, hash(x), hash(x.clear)) 

y = {} 
print(y, hash(y.clear)) 

wyjściowa:

{} 42 287254 
Traceback (most recent call last): 
    File "y.py", line 9, in <module> 
    print(hash(y.clear)) 
TypeError: unhashable type: 'dict'