python 3 dict: .keys(), .values(), and .item()

Ethan Furman ethan at stoneleaf.us
Sat Jan 7 16:48:53 EST 2017


In Python 2 we have:

   dict().keys()   \
   dict().items()   -->  separate list() of the results
   dict().values() /

and

   dict().iter_keys()   \
   dict().iter_items()   -->  integrated iter() of the results
   dict().iter_values() /

By "separate list" I mean a snapshot of the dict at the time, and by
"integrated iter()" I mean  changes to the dict during iteration are
seen by the iter.

In Python 3 the iter_* methods replaced the list() type methods, which
makes sense from the point-of-view of moving to a more iterator based
language; however, as a result of that change the typical "iterate over
a dict" operation now has a built-in gotcha: modifying the dict during
the iteration can now cause exceptions.

The solution, of course, is simple: surround the iterator call with list():

   list(dict.keys())
   list(dict.items())
   list(dict.values())

   for k, v in list(flag._value2member_map_.items()):
       ...

The solution, however, feels a lot more boilerplate-ish.  Either the
programmer takes a lot more care to remember the current state of the dict
(since it's no longer a snapshot), or "list()" is sprinkled around every
iterator access.

In other words, what used to be a completely safe operation now is not.

Thoughts?

--
~Ethan~


More information about the Python-list mailing list