哈希Python类是个好主意吗?

6 投票
2 回答
5821 浏览
提问于 2025-04-15 13:53

比如说,我这样做:

>>> class foo(object):
...     pass
... 
>>> class bar(foo):
...     pass
... 
>>> some_dict = { foo : 'foo',
... bar : 'bar'}
>>> 
>>> some_dict[bar]
'bar'
>>> some_dict[foo]
'foo'
>>> hash(bar)
165007700
>>> id(bar)
165007700

根据这个情况,看起来这个类的ID号是通过哈希值来生成的。因此,我们不需要担心,比如说,一个 bar 会被哈希成 foo 或者 bar,或者如果我修改这个类,哈希值会发生变化。

这种行为可靠吗?有没有什么需要注意的地方?

2 个回答

7

类有默认的 __eq____hash__ 方法,这些方法分别用 id() 来进行比较和计算哈希值。简单来说,它们是通过对象的身份来比较的。实现 __hash__ 方法的主要规则是,如果两个对象被认为是相等的,它们的哈希值也必须相同。哈希值可以看作是字典和集合用来更快找到相等对象的一种优化方式。因此,如果你改变了 __eq__ 方法来进行不同的相等性测试,你也必须相应地修改 __hash__ 的实现,以保持一致。

那些通过身份进行比较的类可以随意修改,并且可以在字典和集合中使用,因为它们的身份是不会改变的。而那些实现了 __eq__ 来通过值进行比较,并且允许修改其值的类,就不能在哈希集合中使用了。

8

是的,任何没有实现 __hash__() 函数的对象在进行哈希处理时,都会返回它的 ID。根据 Python 语言参考:数据模型 - 基本定制 的说明:

用户自定义的类默认有 __cmp__()__hash__() 方法;有了这些方法,所有对象之间的比较结果都是不相等的(除了和它自己比较),而 x.__hash__() 会返回 id(x)

不过,如果你想要一个唯一的标识符,使用 id 可以更清楚地表达你的意图。一个对象的哈希值应该是它各个组成部分哈希值的组合。想了解更多细节,可以查看上面的链接。

撰写回答