使用 union 将字典添加到 `set()`
Add a dictionary to a `set()` with union
我只是 运行 遇到了一些我想问的有趣的事情。
将词典添加到 set
,我原以为该词典将作为完整词典添加,但事实并非如此。仅添加了键:
dicty = {"Key1": "Val1", "Key2": "Val2"}
setunion = set()
setunion.union(dicty)
=> set(['Key2', 'Key1'])
当您尝试使用 set.add()
添加它时出现错误:
setadd = set()
setadd.add(dicty)
Traceback (most recent call last):
File "python", line 1, in <module>
TypeError: unhashable type: 'dict'
显然,此行为与列表有很大不同:
listy = []
listy.append(dicty)
listy
=> [{'Key2': 'Val2', 'Key1': 'Val1'}]
In the docs 它说集合是 hashable 对象的无序集合,这暗示了上面的一些问题。
问题
这是怎么回事?集合项必须是可哈希的,很明显这与为什么我只使用 .union()
将键添加到集合中有关,但为什么 .add()
会出错?
集合与列表的行为差异背后是否存在一些可用性原因?
Python(或库)中是否有一种数据类型本质上像列表一样工作,但只保留唯一项?
不,根据定义这是不可能的。哈希表(如 dict
s 和 set
s)进行查找的方式与数组(如 list
s)进行查找的方式根本不同。逻辑错误是,如果你有一个只保存重复项的数据类型,如果你将其中一个元素变为非唯一的,会发生什么?
a, b = [0], [0, 1]
s = SpecialSet(a, b)
a.append(1) # NOW WHAT?!
如果你想将字典添加到集合中,你可以添加它的 dict.items
视图(实际上只是一个元组列表),但你必须先转换为元组。
a = {1:2, 3:4}
s = set()
s.add(tuple(a.items()))
然后你必须重新转换为 dict,一旦它离开集合以取回字典
for tup in s:
new_a = dict(tup)
在 PEP416 中提出了内置 frozendict
类型,但最终被拒绝了。
使用 set.union()
,要求将方法参数的 元素 添加到集合中,而不是对象本身。遍历字典会为您提供键。如果你在列表、元组或字符串上使用 set.union()
,你会得到类似的结果,其中的 contents 被添加到集合中:
>>> s = {42}
>>> s.union('foo')
set([42, 'o', 'f'])
添加了单字符字符串 'o'
和 'f'
,而不是字符串 'foo'
。
您不能将词典添加到集合中,因为它们可变;集合仅支持存储可散列对象,对象可散列的要求之一是它们是不可变的。
我只是 运行 遇到了一些我想问的有趣的事情。
将词典添加到 set
,我原以为该词典将作为完整词典添加,但事实并非如此。仅添加了键:
dicty = {"Key1": "Val1", "Key2": "Val2"}
setunion = set()
setunion.union(dicty)
=> set(['Key2', 'Key1'])
当您尝试使用 set.add()
添加它时出现错误:
setadd = set()
setadd.add(dicty)
Traceback (most recent call last):
File "python", line 1, in <module>
TypeError: unhashable type: 'dict'
显然,此行为与列表有很大不同:
listy = []
listy.append(dicty)
listy
=> [{'Key2': 'Val2', 'Key1': 'Val1'}]
In the docs 它说集合是 hashable 对象的无序集合,这暗示了上面的一些问题。
问题
这是怎么回事?集合项必须是可哈希的,很明显这与为什么我只使用 .union()
将键添加到集合中有关,但为什么 .add()
会出错?
集合与列表的行为差异背后是否存在一些可用性原因?
Python(或库)中是否有一种数据类型本质上像列表一样工作,但只保留唯一项?
不,根据定义这是不可能的。哈希表(如 dict
s 和 set
s)进行查找的方式与数组(如 list
s)进行查找的方式根本不同。逻辑错误是,如果你有一个只保存重复项的数据类型,如果你将其中一个元素变为非唯一的,会发生什么?
a, b = [0], [0, 1]
s = SpecialSet(a, b)
a.append(1) # NOW WHAT?!
如果你想将字典添加到集合中,你可以添加它的 dict.items
视图(实际上只是一个元组列表),但你必须先转换为元组。
a = {1:2, 3:4}
s = set()
s.add(tuple(a.items()))
然后你必须重新转换为 dict,一旦它离开集合以取回字典
for tup in s:
new_a = dict(tup)
在 PEP416 中提出了内置 frozendict
类型,但最终被拒绝了。
使用 set.union()
,要求将方法参数的 元素 添加到集合中,而不是对象本身。遍历字典会为您提供键。如果你在列表、元组或字符串上使用 set.union()
,你会得到类似的结果,其中的 contents 被添加到集合中:
>>> s = {42}
>>> s.union('foo')
set([42, 'o', 'f'])
添加了单字符字符串 'o'
和 'f'
,而不是字符串 'foo'
。
您不能将词典添加到集合中,因为它们可变;集合仅支持存储可散列对象,对象可散列的要求之一是它们是不可变的。