简体   繁体   English

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

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

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? 为什么这有必要?

You can safely ignore this "extra precautions" warning: your code will work the same even without list in both versions of Python. 您可以放心地忽略这个“额外的预防措施”警告: 即使没有两个版本的Python list ,您的代码也会工作相同。 It would run differently if you needed a list (but this is not the case): in fact, features.items() is a list in Python 2, but a view in Python 3. They work the same when used as an iterable, as in your example. 如果你需要一个列表(但事实并非如此),它将以不同的方式运行:事实上, features.items()是Python 2中的一个列表 ,但是Python 3中的一个视图 。当它们用作可迭代时,它们的工作方式相同,在你的例子中。

Now, the Python 2 to Python 3 conversion tool 2to3 errs on the side of safety, and assumes that you really wanted a list when you use dict.items() . 现在,Python 2到Python 3转换工具2to3在安全方面存在错误,并假设您在使用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 3中的dict.items() (没有包装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 2to3 to features.items() ). 具体来说,这意味着Python 2代码可以显式迭代视图: for k, v in features.viewitems() (将在Python 3中通过2to3features.items() )。 It looks like your IDE thinks that the code is Python 2, because your for statement is very good, in Python 3, so there should be no warning about Python 3 support. 看起来你的IDE认为代码是Python 2,因为你的for语句非常好,在Python 3中,所以不应该有关于Python 3支持的警告。

In Python 2, the methods items() , keys() and values() used to "take a snapshot" of the dictionary contents and return it as a list. 在Python 2中,方法items()keys()values()用于“获取字典内容的快照”并将其作为列表返回。 It meant that if the dictionary changed while you were iterating over the list, the contents in the list would not change. 这意味着如果在迭代列表时字典发生更改,则列表中的内容不会更改。

In Python 3, these methods return a view object whose contents change dynamically as the dictionary changes . 在Python 3中,这些方法返回一个视图对象,其内容随着字典的变化而动态变化 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返回一个字典视图对象而不是Python 2将返回的列表,并且您期望的某些运算符可能不正确 - 如果底层字典发生更改,View对象也会更改(可能在您迭代的代码中)这可能会导致一些不受欢迎的惊喜)。

In Python 3, dict.items() , dict.keys() , and dict.values() are iterators. 在Python 3中, dict.items()dict.keys()dict.values()是迭代器。 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 ). 因此,如果您期望列表,则在执行对列表有效的操作时可能会出现一些错误,但不一定会出现在迭代器上,例如len(dict.items()) (将生成TypeError )。

CORRECTION 更正

The dict_items returned by calling dict.items() in Python 3 does indeed have a __len__() and will not generate a TypeError . dict_items通过调用返回dict.items()在Python 3确实有一个__len__()不会产生TypeError The dict_items object is not a list, however, and does not have list methods, such as append() , index() , etc... 但是, dict_items对象不是列表,并且没有list方法,例如append()index()等...

Also, as the other (I would say much better) answers by Hamidi and Barnes state, dict_items is a view object that will dynamically change when the dict is altered. 另外,作为Hamidi和Barnes状态的另一个(我会说更好)答案, dict_items是一个视图对象,当dict被改变时它将动态地改变。

When converting a project to python 3 using 2to3 , you can disable this by excluding the dict fixer for more concise output: 使用2to3将项目转换为python 3时,可以通过排除dict修复程序来禁用此功能,以获得更简洁的输出:

$ 2to3 -x dict *

Watch out for iteritems() , iterkeys() https://docs.python.org/2/library/2to3.html#2to3fixer-dict and fix by hand. 注意iteritems()iterkeys() https://docs.python.org/2/library/2to3.html#2to3fixer-dict并手动修复。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM