【问题标题】:Get: TypeError: 'dict_values' object does not support indexing when using python 3.2.3 [duplicate]获取:TypeError:'dict_values'对象在使用python 3.2.3时不支持索引[重复]
【发布时间】:2013-06-30 04:16:02
【问题描述】:

这是我的代码:

{names[i]:d.values()[i] for i in range(len(names))}

这在使用 python 2.7.3 时完全正常;但是,当我使用 python 3.2.3 时,我收到一条错误消息,指出 'dict_values' object does not support indexing。如何修改代码以使其与 3.2.3 兼容?

【问题讨论】:

  • values 现在返回一个视图对象 docs.python.org/3.2/library/…
  • 你为什么要依赖从字典返回的values 的顺序?
  • 是的,除非 d 是 OrderedDict,否则这段代码是不可靠的 - 即使是,似乎也必须有更好的方法。
  • 我使用它的一种情况是,当我知道 dict 中只有一个键值时,例如数据库行检索中的一列,每行仅采用 dict 格式。我认为 values() 在索引时无法自动转换是非常糟糕的。

标签: python python-3.x


【解决方案1】:

在 Python 3 中,dict.values()(连同dict.keys()dict.items())返回一个view,而不是一个列表。请参阅文档here。因此,您需要将您对dict.values() 的调用封装在对list 的调用中,如下所示:

v = list(d.values())
{names[i]:v[i] for i in range(len(names))}

【讨论】:

  • OP 的代码对于每个看这个的人来说都是非 Python 的 - 在 Python 中我们避免索引(更慢,更丑)。正确的方法是按照@DavidRobinson 的answer:dict(zip(names, d.values()))。当然,这段代码也依赖于按名称排序的值,这绝不是保证。
  • 如果可以,您愿意解释一下python做出这个决定的理由吗?从幼稚的角度来看,我看不出在这种特殊情况下视图不应该允许索引的任何原因。我认为视图概念背后有一个更宏大的方案,它不与索引一起使用,但希望能有一些清晰性。
  • 对于那些阅读这些 cmets 的人来说,@Mr_and_Mrs_D 的这个实现版本是不安全的。您不应该依赖字典顺序。例如,d=dict(**d) 可能会改变键的迭代顺序。
  • @xaviersjs 不,它可能不在 python 3.7+ 中 - 这是语言的保证。但这与我的评论无关 - 迭代 dict 等同于迭代 keys() 反过来 is 保证与迭代 values() 具有相同的顺序 - 又名 @ 987654334@
【解决方案2】:

您的代码的更简单版本是:

dict(zip(names, d.values()))

如果要保持结构不变,可以改为:

vlst = list(d.values())
{names[i]: vlst[i] for i in range(len(names))}

(您可以轻松地将list(d.values()) 放入理解而不是vlst;这样做只是浪费,因为它每次都会重新生成列表)。

【讨论】:

  • 不幸的是,当我使用 vlst 示例时,我得到一个错误“'dict' object has no attribute 'values'
  • @JessePet:我不明白这怎么可能,尤其是因为在您自己的代码中 d.values() 确实可以正常工作(直到您尝试对其进行索引)。您是否可能拼错了values 或类似的错误?
  • 我没有拼错值,至少可以说让我吃惊
  • @JessePet:如果您打开一个新的 Python3 终端并执行{1: 2}.values(),会发生什么?还是d = {1: 2}; print d.values()
  • 你能粘贴你正在使用的精确代码和你得到的错误吗?
【解决方案3】:

在 Python 3 中,dict.values() 方法返回 dictionary view object,而不是像在 Python 2 中那样的列表。字典视图有长度,可以迭代,并支持成员资格测试,但不支持索引。

要使您的代码在这两个版本中都能正常工作,您可以使用以下任一版本:

{names[i]:value for i,value in enumerate(d.values())}

    

values = list(d.values())
{name:values[i] for i,name in enumerate(names)}

到目前为止,在任一版本中执行相同操作的最简单、最快的方法是:

dict(zip(names, d.values()))

但是请注意,所有这些方法都会为您提供根据d 的实际内容而有所不同的结果。为了克服这个问题,您可以改用OrderedDict,它会记住键首次插入其中的顺序,因此您可以依靠values() 方法返回的顺序。

【讨论】:

  • 更新:请注意,在 Python 3.7+ 中,常规字典保持插入顺序,因此不需要在其中使用 OrderedDict。 (实际上在 CPython 3.6 中也是如此,但尚未正式发布,这意味着在其他实现中可能会有所不同)。
猜你喜欢
  • 1970-01-01
  • 2016-11-30
  • 1970-01-01
  • 2017-12-19
  • 2013-08-23
  • 2018-01-07
  • 2013-06-23
  • 2019-04-18
  • 2016-01-13
相关资源
最近更新 更多