您只能对字典键使用不可变值。set()
值是可变的,因此不能使用:
>>> lst = ['A', 'B', 'C', 'A', 'B']
>>> {{x}: y for x, y in enumerate(lst)}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <dictcomp>
TypeError: unhashable type: 'set'
改为使用frozenset()
值:
{frozenset([x]): y for x, y in enumerate(lst)}
演示:
>>> lst = ['A', 'B', 'C', 'A', 'B']
>>> {frozenset([x]): y for x, y in enumerate(lst)}
{frozenset([4]): 'B', frozenset([2]): 'C', frozenset([3]): 'A', frozenset([0]): 'A', frozenset([1]): 'B'}
字典键必须是可散列的;请参阅映射类型文档:
字典的键几乎是任意值。不可散列的值,即包含列表、字典或其他可变类型的值(按值而不是对象标识进行比较)不能用作键。
和Python 词汇表中的可散列条目:
一个对象是hashable
如果它有一个在其生命周期内永远不会改变的哈希值(它需要一个__hash__()
方法),并且可以与其他对象进行比较(它需要一个__eq__()
或__cmp__()
方法)。比较相等的可散列对象必须具有相同的散列值。
因为set
值是可变的,所以它们不符合可散列标准;现在比较相等的任何两个集合,以后都可以更改为不再相等,因此它们的哈希值也需要更改。因为字典和集合都依赖于不改变的哈希值,所以可变容器不能用作字典键。
字典值(与键相反)不限于可散列对象。
如果您想创建设置值,请使用循环:
dct = {}
for x, y in enumerate(lst):
dct.setdefault(y, set()).add(x)
或改用collections.defaultdict
对象并避免.setdefault()
调用:
from collections import defaultdict
dct = defaultdict(set)
for x, y in enumerate(lst):
dct[y].add(x)
演示:
>>> lst = ['A', 'B', 'C', 'A', 'B']
>>> dct = {}
>>> for x, y in enumerate(lst):
... dct.setdefault(y, set()).add(x)
...
>>> dct
{'A': set([0, 3]), 'C': set([2]), 'B': set([1, 4])}
>>> from collections import defaultdict
>>> dct = defaultdict(set)
>>> for x, y in enumerate(lst):
... dct[y].add(x)
...
>>> dct
defaultdict(<type 'set'>, {'A': set([0, 3]), 'C': set([2]), 'B': set([1, 4])})