【问题标题】:Inconsistent behaviour between dict.items and dict.valuesdict.items 和 dict.values 之间的行为不一致
【发布时间】:2014-08-31 22:00:48
【问题描述】:

注意: 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 也是如此,这里仅设置操作.items 一旦在 dict 中存在不可散列的类型,就会在运行时失败,而 .values 的设置操作会立即失败。

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

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

【问题讨论】:

  • 然而,设置文字将忽略重复项。一般来说,您不希望在 dict 视图中发生这种情况。
  • @MartijnPieters 我不相信,一个 dictview 和一个集合的集合交集返回另一个集合,那么在这个阶段删除重复项会有什么问题? dictview 当然仍然可以包含欺骗。
  • 显式优于隐式;然后将值字典视图转换为集合。
  • @MartijnPieters 你认为它可能已经实现了吗,理论上,它根本就没有通过设计选择来实现?
  • original PEP 没有提及它。但是行为必须是一致的,并且对于不可散列的类型等不会突然失败。要求显式转换为集合会使这一点更加更清晰,符合 Python 设计理念。

标签: python dictionary set dictview


【解决方案1】:

如果你在 leetcode 中编码,那么你可以通过改变结果来实现

return res_dic.values()

return list(res_dic.values())

【讨论】:

    【解决方案2】:

    如果我们values 视为一个集合,那么您会使 values 字典视图成为一个非常昂贵的对象来生成。您必须先计算 所有值 的哈希值,然后才能将其用作集合;您真的不想为大型字典执行此操作,尤其是如果您事先不知道所有值是否都是可散列的。

    因此,将其保留为显式操作要好得多;如果您想将值视为一个集合,明确将其设为一个集合:

    values = set(yourdict.values())
    

    dict.items() 行为源于我们预先知道键至少是唯一的,因此每个 (key, value) 对也是唯一的;在幕后,您可以将成员资格测试委托给键字典视图。

    但是,一旦您对其使用集合操作(​​交集、联合等),您就会创建一个新的set 对象,而不是字典视图。对于这样的set 对象,(键,值)对中的两个元素必须 是可散列的,因为通用的set 类型不能对键做出相同的假设,你也不能保持这一点约束(因为{'a': 0}.items() &amp; {('a', 1)} 是完全合法的,但会导致重复键)。

    【讨论】:

      【解决方案3】:

      因为在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 上不能有重复的键,但values() 上可以有重复的值。这就是为什么keys cuacks 和鸭子喜欢一组,而values cuacks 和鸭子喜欢list

      【讨论】:

      • 那又怎样?我并不是说应该从价值观视图中删除受骗者。我的意思是,如果没有不可哈希的类型阻止它,他们应该支持集合操作。
      • @wim 它与可散列的值无关,仅与作为字典键的元素相关。 keys() 方法返回类似于 set 之类的 cuacks 的东西,因为您不能在 dict 上有重复的键。这就是为什么键像集合一样回避,而值像列表一样回避。
      【解决方案4】:

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

      由于您的值通常是不唯一的项目列表,因此将其转换为集合并不是一个好主意。如果您确实需要,只需手动转换它。我的假设是不允许这样做,因为这通常是个坏主意,因为它可能导致数据丢失。

      【讨论】:

        猜你喜欢
        • 2019-07-28
        • 2021-07-19
        • 1970-01-01
        • 1970-01-01
        • 2016-11-09
        • 2019-06-13
        • 2017-12-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多