当前位置:   article > 正文

Python魔法方法(10):__hash__(self) 方法_hash(self)

hash(self)

Python 的对象天生拥有一些神奇的方法,它们总被双下划线所包围,它们是面向对象的 Python 的一切。它们是可以给你的类增加魔力的特殊方法,如果你的对象实现(重载)了某一个魔法方法,那么这个方法就会在特殊的情况下自动被 Python 所调用。

功能

定义对象被 hash() 函数调用时的行为。

参数

self 表示对象自己。

返回值

一个整数,表示对象的哈希值。

示例

  1. class MyTest(object):
  2. def __init__(self):
  3. self.name = '阿珍'
  4. self.age = 18
  5. def __hash__(self):
  6. return hash(str(self))
  7. sample = MyTest()
  8. 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桶里)。

如下示例:

  1. class Foo:
  2. def __init__(self, item):
  3. self.item = item
  4. def __eq__(self, other):
  5. print('使用了equal函数的对象的id', id(self))
  6. if isinstance(other, self.__class__):
  7. return self.__dict__ == other.__dict__
  8. else:
  9. return False
  10. def __hash__(self):
  11. print('f' + str(self.item) + '使用了hash函数')
  12. return hash(self.item)
  13. f1 = Foo(1)
  14. f2 = Foo(2)
  15. f3 = Foo(3)
  16. fset = set([f1, f2, f3])
  17. print(fset)
  18. print()
  19. f = Foo(3)
  20. fset.add(f)
  21. print('f3的id:', id(f3))
  22. print('f的id:', id(f))


 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/喵喵爱编程/article/detail/812123
推荐阅读
相关标签
  

闽ICP备14008679号