廢話很少說直接祭上python3.3x的文檔:(原文連接)html
object.__hash__(self)python
Called by built-in function hash() and for operations on members of hashed collections including set, frozenset, and dict. __hash__() should return an integer. The only required property is that objects which compare equal have the same hash value; it is advised to somehow mix together (e.g. using exclusive or) the hash values for the components of the object that also play a part in comparison of objects.app
可哈希對象是對象擁有__hash__(self)內置函數的對象。對於可哈希的對象執行這個函數將會返回一個整數。可哈希對象判斷相等的惟一條件就是二者 的哈希值相等。若是咱們的對象有多個屬性值,咱們會使用一種方法(比方說邏輯運算異或)來將其屬性值結合在一塊兒作比較。(若是不對,麻煩必定告訴我,謝謝!)ide
If a class does not define an __eq__() method it should not define a __hash__() operation either; if it defines __eq__() but not __hash__(), its instances will not be usable as items in hashable collections. If a class defines mutable objects and implements an __eq__() method, it should not implement __hash__(), since the implementation of hashable collections requires that a key’s hash value is immutable (if the object’s hash value changes, it will be in the wrong hash bucket).函數
若是一個類型定義沒有定義__eq__()函數,那麼它也不該該定義__hash__();由於若是它定義了__eq__而沒有定義__hash__,那麼它的實例在某個可哈希集合中將會無效(比方說在字典/集合這類類型中)。若是一個類型定義了一個可變對象並且定義了__eq__方法,那麼它不該該去定義__hash__方法,由於在哈希集合中要求其中元素的哈希值是不變的(若是某個對象實例的哈希值發生了改變,那麼他將會到錯誤的哈希表中。。)。ui
User-defined classes have __eq__() and __hash__() methods by default; with them, all objects compare unequal (except with themselves) and x.__hash__() returns an appropriate value such that x == y implies both that x is y and hash(x) == hash(y).this
用戶定義的類中都有默認的__eq__和__hash__方法;有了它,全部的對象實例都是不等的(除非是本身和本身比較),在作 x == y 比較時是和這個等價的 hash(x) == hash(y)。spa
A class that overrides __eq__() and does not define __hash__() will have its __hash__() implicitly set to None. When the __hash__() method of a class is None, instances of the class will raise an appropriate TypeError when a program attempts to retrieve their hash value, and will also be correctly identified as unhashable when checking isinstance(obj, collections.Hashable).code
這句話的意思是,若是咱們定義了一個類型,該類型只定義了__eq__而沒有定義__hash__的話,那麼他的__hash__()會隱式的設置爲None,若是某個狀況下須要這個類型的哈希值,那麼程序將會報錯。具體請看下面代碼:component
>>> class A: ... def __eq__(self, other): ... return True ... >>> a = A() >>> import collections >>> isinstance(a, collections.Hashable) # 發現它不是可哈希對象 False >>> a.__hash__ >>> a.__hash__() Traceback (most recent call last): File "<ipython-input-20-0fddd0562e01>", line 1, in <module> a.__hash__() TypeError: 'NoneType' object is not callable
而後往下看文檔
If a class that overrides __eq__() needs to retain the implementation of __hash__() from a parent class, the interpreter must be told this explicitly by setting __hash__ = <ParentClass>.__hash__.
若是某個重寫了__eq__方法的對象須要保留__hash__屬性,那麼咱們須要在類型設置中添加該語句 __hash__ = <ParentClass>.__hash__
請看代碼
>>> class A: ... __hash__ = object.__hash__ ... def __eq__(self, other): ... return True ... >>> a = A() >>> a.__hash__ <method-wrapper '__hash__' of A object at 0x7f21029cfa10> >>> set([a,2,3]) {<__main__.A object at 0x7f21029cfa10>, 2, 3}
If a class that does not override __eq__() wishes to suppress hash support, it should include __hash__ = None in the class definition. A class which defines its own __hash__() that explicitly raises a TypeError would be incorrectly identified as hashable by an isinstance(obj, collections.Hashable) call.
若是某個類型定義須要將__hash__屬性刪掉,那麼咱們能夠在類變量中這樣寫 __hash__ = None
看完了仍是有點小激動的,今天由於一個偶然緣由,接觸到了這麼多的python知識。真的是至關高興阿!
然而我也發現__eq__ __hash__這兩個方法不能隨意動,若是我麼須要改寫其中一個的話必定要仔細考慮可能的狀況,以避免出現問題。