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

Question:

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?

Asked By: Jesse Pet

||

Answers:

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

Answered By: David Robinson

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))}
Answered By: andersschuller

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

Answered By: martineau
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.