7

在我输入的控制台上

>>> class S(str): pass
...
>>> a = 'hello'
>>> b = S('hello')
>>> d = {a:a, b:b}
>>> d
{'hello': 'hello'}
>>> type(d[a])
<class '__main__.S'>
>>> type(d[b])
<class '__main__.S'>

起初我以为d只保留一对的原因是因为hash(a)hash(b)返回相同的值,所以我尝试了:

>>> class A(object):
...     def __hash__(self):
...             return 0
... 
>>> class B(object):
...     def __hash__(self):
...             return 0
... 
>>> d = {A():A(),B():B()}
>>> d
{<__main__.A object at 0x101808b90>: <__main__.A object at 0x101808b10>, <__main__.B object at 0x101808d10>: <__main__.B object at 0x101808cd0>}

现在我很困惑。为什么在第一个代码清单中d只保留了一对,但在第二个清单d中,尽管具有相同的哈希值,两个键都被保留了?

4

4 回答 4

8

原始示例中的两个对象被折叠不是因为它们具有相同的哈希值,而是因为它们比较相等。字典键在相等性方面是唯一的,而不是散列。Python 要求任何两个比较相等的对象必须具有相同的哈希值(但不一定相反)。

在您的第一个示例中,这两个对象是相等的,因为它们都具有str相等行为。由于两个对象比较相等,因此它们被折叠为一个。在第二个示例中,它们的比较不相等。默认情况下,用户定义的类使用标识来表示相等 --- 也就是说,每个对象仅与自身比较相等。所以你的两个对象不相等。它们具有相同的哈希无关紧要。

于 2012-12-21T05:01:00.907 回答
4

哈希不能确定字典中的唯一键。在某些方面,散列函数是“实现细节”,因为它们确定字典内部如何存储其条目。a == b 意味着 hash(a) == hash(b),但反之亦然。两个键还需要彼此相等(当应用 == 运算符时)才能被视为字典中的等效键。

于 2012-12-21T05:01:54.330 回答
2

如果您希望类型是可散列的,那么您还必须定义__eq__(). str定义__eq__()正确,但AB正确。

于 2012-12-21T04:59:40.433 回答
0

第一个和第二个对象的键不同。因为它们是对象,所以键是对象的一些可读等价物,而不是字符串。

于 2012-12-21T05:01:18.503 回答