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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17695456/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 08:56:21  来源:igfitidea点击:

Why does Python 3 need dict.items to be wrapped with list()?

pythonpython-3.xpython-2to3

提问by Dewfy

I'm using Python 3. I've just installed a Python IDE and I am curious about the following code warning:

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

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

Warning is: "For Python3 support should look like ... list(features.items())"

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

Also there is mention about this at http://docs.python.org/2/library/2to3.html#fixers

http://docs.python.org/2/library/2to3.html#fixers也提到了这一点

It also wraps existing usages of dict.items(), dict.keys(), and dict.values() in a call to list.

它还在对列表的调用中包装了 dict.items()、dict.keys() 和 dict.values() 的现有用法。

Why is this necessary?

为什么这是必要的?

采纳答案by Eric O Lebigot

You can safely ignore this "extra precautions" warning: your code will work the same even without listin both versions of Python. It would run differently if you needed a list (but this is not the case): in fact, features.items()is a listin Python?2, but a viewin Python?3. They work the same when used as an iterable, as in your example.

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

Now, the Python?2 to Python?3 conversion tool 2to3errs on the side of safety, and assumes that you really wanted a listwhen you use dict.items(). This may not be the case (as in the question), in which case dict.items()in Python?3 (no wrapping list) is better (faster, and less memory-consuming, since no list is built).

现在,Python的?2到Python?3转换工具2to3在安全方面ERRS,并假定你真的想要一个列表,当您使用dict.items()。情况可能并非如此(如问题所示),在这种情况下dict.items(),Python?3(无包装list)更好(更快,内存消耗更少,因为没有构建列表)。

Concretely, this means that Python?2 code can explicitly iterate over the view: for k, v in features.viewitems()(which will be converted in Python?3 by 2to3to features.items()). It looks like your IDE thinks that the code is Python?2, because your forstatement is very good, in Python?3, so there should be no warning about Python?3 support.

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

回答by Joel Cornett

In Python 3, dict.items(), dict.keys(), and dict.values()are iterators. Therefore if you are expecting a list, you might get some errors when doing operations that work on lists, but not necessarily on iterators, such as len(dict.items())(will generate a TypeError).

在 Python 3 中,dict.items(), dict.keys(), 和dict.values()是迭代器。因此,如果您需要一个列表,那么在对列表进行操作时可能会遇到一些错误,但不一定对迭代器进行操作,例如len(dict.items())(将生成一个TypeError)。

CORRECTION

更正

The dict_itemsreturned by calling dict.items()in Python 3 does indeed have a __len__()and will notgenerate a TypeError. The dict_itemsobject is not a list, however, and does not have listmethods, such as append(), index(), etc...

dict_items调用返回dict.items()Python 3中确实有一个__len__(),将不会产生TypeError。该dict_items物体是不是列表,但是,没有list方法,如append()index()等...

Also, as the other (I would say much better) answers by Hamidi and Barnes state, dict_itemsis a view object that will dynamically change when the dictis altered.

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

回答by Frédéric Hamidi

In Python 2, the methods items(), keys()and values()used to "take a snapshot" of the dictionary contents and return it as a list. It meant that if the dictionary changed while you were iterating over the list, the contents in the list would notchange.

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

In Python 3, these methods return a view objectwhose contents change dynamically as the dictionary changes. Therefore, in order for the behavior of iterations over the result of these methods to remain consistent with previous versions, an additional call to list()has to be performed in Python 3 to "take a snapshot" of the view object contents.

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

回答by Steve Barnes

Python 3 returns a Dictionary View Objectrather than a list which Python 2 would return and some operators that you would expect may not be true - also a View Object will change if the underlying dictionary changes, (possibly in the code that you are iterating through which could cause some unwelcome surprises).

Python 3 返回一个字典视图对象,而不是 Python 2 将返回的列表,并且您期望的一些运算符可能不正确 - 如果底层字典发生变化,视图对象也会发生变化(可能在您迭代的代码中)这可能会导致一些不受欢迎的惊喜)。

回答by line break

When converting a project to python 3 using 2to3, you can disable this by excluding the dictfixer for more concise output:

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

$ 2to3 -x dict *

Watch out for iteritems(), iterkeys()https://docs.python.org/2/library/2to3.html#2to3fixer-dictand fix by hand.

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