7

我刚刚遇到了一些我想问的有趣的事情。

将字典添加到 aset中,我曾假设该字典将作为完整字典添加,但事实并非如此。仅添加键:

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'}]

在文档中,它说集合是可散列对象的无序集合,这是对上述一些问题的暗示。

问题

这里发生了什么?集合项必须是可散列的,所以很明显,这与为什么我只用 将键添加到集合中.union(),但为什么用.add()?

列表中集合的行为差异背后是否存在一些可用性原因?

Python(或库)中是否存在本质上类似于列表但仅保留唯一项的数据类型?

4

2 回答 2

16

不,根据定义,这是不可能的。哈希表(如dicts 和sets)进行查找的方式与数组(如lists)进行查找的方式基本不同。逻辑错误是,如果你有一个只保存重复的数据类型,如果你将其中一个元素改变为非唯一的会发生什么?

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)

PEP416frozendict中提出了一种内置类型,但最终被拒绝。

于 2015-12-04T21:46:44.650 回答
5

使用set.union(),请求将方法的参数元素添加到集合中,而不是对象本身。遍历字典会为您提供键。如果您set.union()在列表、元组或字符串上使用,您会得到类似的结果,它们的内容将添加到集合中:

>>> s = {42}
>>> s.union('foo')
set([42, 'o', 'f'])

添加了单字符串'o''f',而不是字符串'foo'

您不能将字典添加到集合中,因为它们是可变的;集合仅支持存储可散列对象,而对象可散列的要求之一是它们是不可变的。

于 2015-12-04T21:51:17.030 回答