dict.items和dict.values之间的行为不一致

时间:2014-07-10 13:37:58

标签: python dictionary set dictview

注意: python3中的代码示例,但问题也代表python2(将.keys替换为.viewkeys等)

dict个对象提供了(有时)支持集合操作的视图方法:

>>> {'a': 0, 'b': 1}.keys() & {'a'}
{'a'}
>>> {'a': 0, 'b': 1}.items() & {('a', 0)}
{('a', 0)}

但是值视图不支持集合运算符:

>>> {'a': 0, 'b': 1}.values() & {0}
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for &: 'dict_values' and 'set'

我理解dict值可以是不可清除的对象,因此并不总是可以创建一组值,但dict.items也是如此,而这里是集合只有在dict 中存在不可用类型时,.items才会在运行时失败,而.values的设置操作会立即失败。

文档提到Values views are not treated as set-like since the entries are generally not unique,但这似乎并不是一个令人信服的理由 - 例如,python不会阻止您创建像{0, 0, 1, 2}这样的集合文字。

这种行为不一致的真正原因是什么?

4 个答案:

答案 0 :(得分:3)

如果我们 视为一个集合,那么您将使值字典视图成为一个非常昂贵的对象。您必须先计算所有值的哈希值,然后才能将其用作集合;你真的不想为一本大字典做这件事,特别是如果你不知道所有的价值是否可以清洗。

因此,这最好留作明确的操作;如果您想将值视为一个集合,显式使其成为一个集合:

values = set(yourdict.values())

dict.items()行为源于这样一个事实:我们事先知道密钥至少是唯一的,因此每个(密钥,值)对也是唯一的;在封面下,您可以将成员资格测试委托给密钥字典视图。

但是只要你对它(交集,联合等)使用set操作,你就会创建一个 new set对象,而不是字典视图。对于这样的set对象,(key,value)对中的两个元素必须是可散列的,因为泛型set类型不能对键做出相同的假设,也不能你能保持这种约束吗(因为{'a': 0}.items() & {('a', 1)}是完全合法的,但会导致重复的密钥)。

答案 1 :(得分:0)

因为在dict中,您不能重复keys个值,但您可以重复values个值:

>>> d = {0: 0, 1: 0, 2: 0, 3: 0, 4: 0}
>>> d.keys()
[0, 1, 2, 3, 4]
>>> d.values()
[0, 0, 0, 0, 0]
>>> d.items()
[(0, 0), (1, 0), (2, 0), (3, 0), (4, 0)]

keys()方法返回cuacks and ducks之类的内容,例如set,因为dict上没有重复键,但您可以在{{1}上重复显示值}}。这就是为什么values()keys一样诅咒和躲避values诅咒和像list一样的鸭子。

答案 2 :(得分:0)

原因是它没有在dict_values类型中实现,或者因为dict_values类明确禁止它。

由于您的值通常是一个非唯一的项目列表,因此将其转换为集合并不是一个好主意。如果你想要,只需手动转换它。我的假设是它被禁止,因为它通常是一个坏主意,因为它可能导致数据丢失。

答案 3 :(得分:-2)

如果使用leetcode编码,则可以通过更改

的结果来实现
return res_dic.values()

return list(res_dic.values())