为什么Python 3需要用list()包装dict.items?

时间:2013-07-17 09:00:05

标签: python python-3.x python-2to3

我正在使用Python 3.我刚刚安装了一个Python IDE,我对以下代码警告感到好奇:

features = { ... }
for k, v in features.items():
    print("%s=%s" % (k, v))

警告是:“对于Python3支持应该看起来像...... list(features.items())

http://docs.python.org/2/library/2to3.html#fixers

也有提及
  

它还包含对列表调用中dict.items(),dict.keys()和dict.values()的现有用法。

为什么这有必要?

5 个答案:

答案 0 :(得分:38)

您可以放心地忽略这个“额外预防措施”警告:即使没有list ,您的代码也会在两个版本的Python中使用相同的。如果你需要一个列表,它将以不同的方式运行(但事实并非如此):事实上,features.items()是Python 2中的列表,但 view Python 3中的。当用作可迭代时,它们的工作方式相同,如您的示例所示。

现在,Python 2到Python 3转换工具2to3在安全方面存在错误,并假设您在使用dict.items()时确实需要列表。这可能不是这种情况(如问题所示),在这种情况下,Python 3中的dict.items()(没有包装list)更好(更快,更少内存消耗,因为没有构建列表)

具体地说,这意味着Python 2代码可以显式迭代视图:for k, v in features.viewitems()(将在{3}中将2to3转换为features.items())。看起来你的IDE认为代码是Python 2,因为你的for语句非常好,在Python 3中,所以不应该警告Python 3支持。

答案 1 :(得分:28)

在Python 2中,方法items()keys()values()用于“获取字典内容的快照”并将其作为列表返回。这意味着如果在迭代列表时字典发生更改,列表中的内容将更改。

在Python 3中,这些方法返回view object,其内容在字典更改时动态更改。因此,为了使这些方法的结果上的迭代行为与先前版本保持一致,必须在Python 3中执行对list()的附加调用以“获取视图对象内容的快照”。

答案 2 :(得分:6)

Python 3返回Dictionary View Object而不是Python 2将返回的列表,并且您期望的某些运算符可能不正确 - 如果基础字典发生更改,View对象也会更改(可能在代码中)你正在迭代,这可能会导致一些不受欢迎的惊喜。)

答案 3 :(得分:2)

在Python 3中,dict.items()dict.keys()dict.values()是迭代器。因此,如果您期望列表,则在执行可用于列表的操作时可能会出现一些错误,但不一定会出现在迭代器上,例如len(dict.items())(将生成TypeError)。 < / p>

<强> CORRECTION

通过在Python 3中调用dict_items返回的dict.items()确实有__len__()并且生成TypeError。但是,dict_items对象不是列表,并且没有list方法,例如append()index()等...

另外,正如Hamidi和Barnes状态的另一个(我会说更好)答案,dict_items是一个视图对象,当dict被更改时会动态改变。

答案 4 :(得分:0)

使用2to3将项目转换为python 3时,可以通过排除dict修复程序来禁用此功能,以获得更简洁的输出:

$ 2to3 -x dict *

留意iteritems()iterkeys() https://docs.python.org/2/library/2to3.html#2to3fixer-dict并手动修复。