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