Get: TypeError: 'dict_values' object does not support indexing when using python 3.2.3

PythonPython 3.x

Python Problem Overview


This is my code:

{names[i]:d.values()[i] for i in range(len(names))}

This works completely fine when using python 2.7.3; however, when I use python 3.2.3, I get an error stating 'dict_values' object does not support indexing. How can I modify the code to make it compatible for 3.2.3?

Python Solutions


Solution 1 - Python

In Python 3, dict.values() (along with dict.keys() and dict.items()) returns a view, rather than a list. See the documentation here. You therefore need to wrap your call to dict.values() in a call to list like so:

v = list(d.values())
{names[i]:v[i] for i in range(len(names))}

Solution 2 - Python

A simpler version of your code would be:

dict(zip(names, d.values()))

If you want to keep the same structure, you can change it to:

vlst = list(d.values())
{names[i]: vlst[i] for i in range(len(names))}

(You can just as easily put list(d.values()) inside the comprehension instead of vlst; it's just wasteful to do so since it would be re-generating the list every time).

Solution 3 - Python

In Python 3 the dict.values() method returns a dictionary view object, not a list like it does in Python 2. Dictionary views have a length, can be iterated, and support membership testing, but don't support indexing.

To make your code work in both versions, you could use either of these:

{names[i]:value for i,value in enumerate(d.values())}

    or

values = list(d.values())
{name:values[i] for i,name in enumerate(names)}

By far the simplest, fastest way to do the same thing in either version would be:

dict(zip(names, d.values()))

since zip() doesn't care one way or the other.

Note however, that all of these methods will give you results that will vary depending on the actual contents of d. To overcome that, you may be able use an OrderedDict instead, which remembers the order that keys were first inserted into it, so you can count on the order of what is returned by the values() method.

Update in Python 3.7+ regular dictionaries maintain insertion order, so using an OrderedDict would no longer be necessary. (Actually they were also that way in CPython 3.6, but it wasn't official yet — i.e. in the sense that it was merely an implementation detail, not part of the language specification).

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJesse PetView Question on Stackoverflow
Solution 1 - PythonandersschullerView Answer on Stackoverflow
Solution 2 - PythonDavid RobinsonView Answer on Stackoverflow
Solution 3 - PythonmartineauView Answer on Stackoverflow