所以我浏览了几本书和网站。大多数列出的可能数据类型都是不可变的。我理解可变数据类型如何导致问题。
此外,元组被提及为可能的键,但是当您创建元组元素列表时,它会引发错误。所以我认为任何键,只要它是不可变的是字典可以接受的。这是对的吗?
答案 0 :(得分:7)
任何对象,只要是hashable,都可以用作密钥:
如果对象具有在其生命周期内永远不会更改的哈希值(它需要
__hash__()
方法),并且可以与其他对象进行比较(它需要__eq__()
或{{ 1}}方法)。比较相等的Hashable对象必须具有相同的哈希值。
不变性使得生成稳定的哈希成为可能,但只要不改变用于生成哈希的状态,就可以使用可变的自定义类。
如果元组仅包含可清除对象,则它们只能清除;元组的散列由内容的散列决定,因为这也决定了两个元组是否相等。您不能对包含列表的元组进行哈希处理,例如:
__cmp__()
列表不可清除,因为它也必须从内容构建一个哈希值(因为它使用内容来确定两个列表是否相等),但是这个哈希值会在列表的生命周期内发生变化,因为你很容易变异列表中的内容。
自定义类可以用作键,前提是哈希基于使两个对象相等的相同变量。自定义类的默认实现是,如果它们是完全相同的实例,则只有两个实例相同,默认情况下使它们可以清除。但是下面的类也是可以清除的,因为更改的数据是而不是用于确定相等:
>>> l = ['foo', 'bar']
>>> t = (42, l) # contains a list
>>> hash(t)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
该类变异class HashableDemo(object):
def __init__(self, value):
self._value = value
self._count = 0
def increment(self):
self._count += 1
def __eq__(self, other):
if not isinstance(other, HashableDemo):
return False
return self._value == other._value
def __hash__(self):
return hash(self._value)
但该属性不用于确定相等性,使哈希保持稳定。