赞
踩
Python 的对象天生拥有一些神奇的方法,它们总被双下划线所包围,它们是面向对象的 Python 的一切。它们是可以给你的类增加魔力的特殊方法,如果你的对象实现(重载)了某一个魔法方法,那么这个方法就会在特殊的情况下自动被 Python 所调用。
功能
定义对象被 hash() 函数调用时的行为。
参数
self 表示对象自己。
返回值
一个整数,表示对象的哈希值。
示例
- class MyTest(object):
-
- def __init__(self):
- self.name = '阿珍'
- self.age = 18
-
- def __hash__(self):
- return hash(str(self))
-
-
- sample = MyTest()
- print(hash(sample))
'运行
python3 中,在 set,frozenset,dict 这三种数据结构中,都要求键值 key 是可 hash 的,因为要保证 key 的唯一性。
而__hash__实际上是返回一个 int 值,用来唯一标记这个对象。
一般讲解 hash 时,同时需要使用 eq。
可哈希的集合(hashed collections),需要集合的元素实现了__eq__和__hash__,而这两个方法可以比喻如下:
哈希集合就是很多个桶,但每个桶里面只能放一个球。
__hash__ 函数的作用就是找到桶的位置,到底是几号桶。
__eq__ 函数的作用就是当桶里面已经有一个球了,但又来了一个球,它声称它也应该装进这个桶里面(__hash__函数给它说了桶的位置),双方僵持不下,那就得用 __eq__ 函数来判断这两个球是不是相等的(equal),如果是判断是相等的,那么后来那个球就不应该放进桶里,哈希集合维持现状。
当可哈希集合(set,frozenset,dict)调用hash函数时,应该返回一个int值。唯一的要求就是,如果判断两个对象相等,那么他们的hash值也应该相等。当比较两个对象相等时是使用对象的成员来比较时,建议要把成员弄进元祖里,再得到这个元祖的hash值来比较。
当class没有定义__eq__()方法时,那么它也不应该定义__hash__()方法。如果它定义了__eq__()方法,却没有定义__hash__()方法,那么这个类的实例就不能在可哈希集合使用。如果一个类定义了一个可变对象(这里应该是指class的成员之一为可变对象),且implement了__eq__()方法,那么这个类就不应该implement __hash__()方法,因为可哈希对象的实现(implement )要求键值key的hash值是不变的(如果一个对象的hash值改变了,那么它会被放在错误的hash桶里)。
如下示例:
- class Foo:
- def __init__(self, item):
- self.item = item
-
- def __eq__(self, other):
- print('使用了equal函数的对象的id', id(self))
- if isinstance(other, self.__class__):
- return self.__dict__ == other.__dict__
- else:
- return False
-
- def __hash__(self):
- print('f' + str(self.item) + '使用了hash函数')
- return hash(self.item)
-
-
- f1 = Foo(1)
- f2 = Foo(2)
- f3 = Foo(3)
- fset = set([f1, f2, f3])
- print(fset)
- print()
- f = Foo(3)
- fset.add(f)
- print('f3的id:', id(f3))
- print('f的id:', id(f))
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。