Reputation: 12394
I wonder why there are these two ways to iterate over a dictionary
states = {
'Oregon': 'OR',
'Florida': 'FL',
'California': 'CA',
'New York': 'NY',
'Michigan': 'MI'
}
for key, item in states.items():
print(key, item)
for key, item in list(states.items()):
print(key, item
As far as I understand, they do the same. Or is there a difference?
Upvotes: 2
Views: 79
Reputation: 71580
Well they are the same in this particular example. As you can see:
>>> states.items()
dict_items([('Oregon', 'OR'), ('Florida', 'FL'), ('California', 'CA'), ('New York', 'NY'), ('Michigan', 'MI')])
>>> type(_)
<class 'dict_items'>
>>>
The items
function returns a dict_items
object.
And it has a __iter__
attribute:
>>> dir(states.items())
['__and__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__rand__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__ror__', '__rsub__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__xor__', 'isdisjoint']
>>>
Which means it supports iteration.
But if you try anything with it:
>>> states.items()[0]
Traceback (most recent call last):
File "<pyshell#21>", line 1, in <module>
states.items()[0]
TypeError: 'dict_items' object is not subscriptable
>>>
It would give a TypeError
.
The dict_items
class is something like:
class dict_items:
...
def __iter__(self):
...
It supports iteration but nothing else.
Whereas if you convert it to a list
:
>>> list(states.items())
[('Oregon', 'OR'), ('Florida', 'FL'), ('California', 'CA'), ('New York', 'NY'), ('Michigan', 'MI')]
>>>
It would give a regular list of tuples, that is obviously iterable as well, but it is completely not needed in this situation.
As @juanpa.arrivillaga mentioned, using list(states.items())
needlessly creates a list of tuples and iterates over that instead of iterating over the items-view directly.
In some other situations, using list
is required. If you want to convert a dictionary to a list of tuples, list(states.items())
would be the way to go.
Upvotes: 3
Reputation: 27609
The main reason you might want to iterate over a list of the items is that it allows you to modify the dict during the iteration, adding new items to the dict or removing old ones.
If you iterate over the dict directly and make such modifications, the iteration will complain with an error and crash.
It won't crash if you just modify the values belonging to existing keys, but in that case, the iteration with the list gives you the old values while iterating over the dict directly gives you the current (possibly already changed during earlier items) values. Getting the old values might be what you want if you for example write a game of life simulator and need to compute the next state from the old state, without the computation of the next state affecting itself.
Doesn't need to be a list, just needs to be some copy of the items, so you're not iterating over the dict directly. Could for example use tuple, deqeue or even dict instead.
If you don't want to modify but just print like in your toy example, then creating the list is just a pointless waste of memory and time.
Upvotes: 1