【问题标题】:TypeError: unsupported operand type(s) for +: 'dict_items' and 'dict_items'类型错误:+ 不支持的操作数类型:“dict_items”和“dict_items”
【发布时间】:2012-11-01 22:15:09
【问题描述】:

我试着像这样总结两个字典:

my_new_dict = dict(my_existing_dict.items() + my_new_dict.items())

但收到错误

TypeError: unsupported operand type(s) for +: 'dict_items' and 'dict_items'

我做错了什么?

【问题讨论】:

  • 旁注:如果你想遍历两个字典,并且你知道它们有唯一的键(或者如果你处理相同的键两次都没关系),请考虑使用 itertools.chain(dict_a, dict_b)

标签: python python-3.x


【解决方案1】:

从 Python 3.9(尤其是PEP 584)开始,dicts 像集合一样获得联合(|)和更新(|=)操作,因此这成为实现您正在寻找的“一种真正的方式”为。

d1 | d2

该 PEP 列出了早期 Python 版本中可用的其他选项,这些选项都有其缺点。如果您使用 PEP 448 (Python 3.5),我建议您使用:

{**d1, **d2}

这是将两个字典解包成一个新字典,从而形成一个联合。

一个问题是你想要的行为是模棱两可的——字典不能有重复的键,所以如果两者都包含相同的键,你就不清楚你想要发生什么。规范明确说明了使用此方法时会发生什么:

在字典中,后面的值总是会覆盖前面的值

如果你想要相反的行为,你可以简单地交换字典中文字的顺序。

你的方法不起作用,因为dictionary views are set-like,所以他们没有实现加法。

您可能想要的是union:d1.items() | d2.items(),它将为您提供一组(key, value) 元组。如果您随后将其传递给 dict() 并且有重复项,则“最后一个”值将是使用的值,但是集合(与视图本身不同)是无序的,因此无法保证哪个项目最终会“第一个”在组合集合中,这意味着哪个“获胜”将是任意的。

所以,简而言之,只要订单/重复选择不重要:

dict(d1.items() | d2.items())

在 Python 2 中,dict.items() 只返回一个 list,您的方法将在其中起作用。

【讨论】:

  • 当我尝试这个时,我得到:TypeError: unhashable type: 'dict'
  • 使用 Python 3.6.1,我注意到如果一个项目同时在 d1d2 中,似乎 dict(d1.items() | d2.items()) 导致 d1 的项目生效在重复的情况下,这不是我所期望的。 dict(list(d1.items()) + list(d2.items())) 的行为与我预期的一样,d2 在重复的情况下获胜。
  • @erwaman 是的,集合是无序的,而字典(现在)是有序的。我的措辞具有误导性,因为当任意订购集合时,“最后一个”没有多大意义。如果你想保持顺序,你确实需要使用像列表这样的有序集合(构建它们的额外成本很小)。
  • @erwaman 查看我的最新编辑,了解我认为在所有情况下都是最佳选择的更新方法。
【解决方案2】:

在 python3 中,dict.items() 返回一个类型为 dict_items 的对象,显然无法添加该对象。 (在 python 2 中,它返回一个可以添加的list)。

另一种添加适用于 py2k 和 py3k 的字典的替代方法:

d = dict1.copy()
d.update(dict2)

当然,在发生键冲突的情况下,您希望发生的事情有些模棱两可。例如如果两个字典都有key1,那么应该在输出中保留谁的key1?或者你应该使用它们两个值的某种组合?在后一种情况下,您可能需要来自 collections 模块的东西(defaultdictCounter

【讨论】:

  • @mgilson:我认为3+中的dict.items()相当于2.6中的dict.iteritems(),也就是它是一个迭代器。
  • @PierreGM 不,它返回一个字典视图,它是一个类似集合的容器(见我的回答)。
【解决方案3】:

其他建议答案的另一种方法是:

dict(list(d1.items()) + list(d2.items()))

如果d1d2 中都存在键,则最终字典中将使用d2 中的值。

【讨论】:

  • 必须是新的,在 3.5.2 中不起作用,但在 3.6.9 中起作用。希望他们只添加 dictN.items() + dictN.items() 的常识语法...
猜你喜欢
  • 1970-01-01
  • 2017-05-27
  • 2014-06-15
  • 2019-04-08
  • 2019-04-05
  • 2018-09-01
  • 2013-10-04
  • 2018-07-07
  • 2021-06-16
相关资源
最近更新 更多