废话很少说直接祭上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__这两个方法不能随意动,若是我么须要改写其中一个的话必定要仔细考虑可能的状况,以避免出现问题。