63

我正在使用 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() 的现有用法。

为什么这是必要的?

4

5 回答 5

56

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

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

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

于 2013-07-17T09:15:08.870 回答
51

在 Python 2 中,方法items()keys()用于values()“拍摄”字典内容的快照并将其作为列表返回。这意味着如果在您遍历列表时字典发生了变化,列表中的内容不会改变。

在 Python 3 中,这些方法返回一个视图对象,其内容随着字典的变化而动态变化。因此,为了使这些方法的结果的迭代行为与以前的版本保持一致,list()必须在 Python 3 中执行额外的调用以“获取视图对象内容的快照”。

于 2013-07-17T09:10:36.053 回答
7

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

于 2013-07-17T09:12:08.860 回答
3

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

$ 2to3 -x dict *

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

于 2015-02-04T12:44:04.757 回答
2

在 Python 3 中dict.items()dict.keys()、 和dict.values()是迭代器。因此,如果您期待一个列表,则在执行适用于列表的操作时可能会遇到一些错误,但不一定适用于迭代器,例如len(dict.items())(will generate a TypeError)。

更正

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

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

于 2013-07-17T09:05:37.670 回答