使用union将字典添加到`set()`

时间:2015-12-04 21:42:46

标签: python dictionary set hashable

我刚遇到了一些我认为应该问的有趣的事情。

将字典添加到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(或库)中是否存在基本上像列表一样的数据类型,但只保留唯一项?

2 个答案:

答案 0 :(得分:8)

根据定义,这是不可能的。散列表(如dictset 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类型,但最终被拒绝了。

答案 1 :(得分:4)

使用StartIndependentWorkTask(),要求将要添加到集合的方法的参数的元素,而不是对象本身。迭代字典会为您提供密钥。如果您在列表,元组或字符串上使用set.union(),那么内容会添加到集合中,您会得到类似的结果:

set.union()

添加了单字符字符串>>> s = {42} >>> s.union('foo') set([42, 'o', 'f']) 'o',而不是字符串'f'

您无法将字典添加到集合中,因为它们是可变的; set只支持存储可哈希的对象,并且对象可以清除的要求之一是它们是不可变的。