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

Dewfy picture Dewfy · Jul 17, 2013 · Viewed 51.4k times · Source

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

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

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

Also there is mention about this at 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.

Why is this necessary?

Answer

Eric O Lebigot picture Eric O Lebigot · Jul 17, 2013

You can safely ignore this "extra precautions" warning: your code will work the same even without list in 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 list in Python 2, but a view in Python 3. They work the same when used as an iterable, as in your example.

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(). 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).

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()). 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.