[Python-ideas] Syntax for key-value iteration over mappings

Rob Cliffe rob.cliffe at btinternet.com
Mon Jul 27 03:52:29 CEST 2015

On 26/07/2015 17:09, Petr Viktorin wrote:
> Hello,
> Currently, the way to iterate over keys and values of a mapping
> is to call items() and iterate over the resulting view::
>      for key, value in a_dict.items():
>          print(key, value)
> I believe that looping over all the data in a dict is a very imporant
> operation, and I find myself writing this quite often. Every time I do,
> it seems it's boilerplate; it looks a like a workaround rather than a
> preferred way of doing things.
> In dict comprehensions and literals, key-value pairs are separated by
> colons. How about allowing that in for loops as well?
>      for key: value in a_dict:
>          print(key, value)
> I argue that to anyone familiar with dict literals, let alone dict
> comprehensions, the semantics of this loop should be pretty obvious.
> In dict comprehensions, similarity to existing syntax becomes even
> more clear:
>      a_mapping = {1: 'one', 2: 'two'}
>      inverse = {val: key for key: val in a_mapping}
> I've bounced this idea off a few EuroPython sprinters, and got some
> questions/concerns I can answer here:
> * But, the colon is supposed to start a block!
> Well, it's already used in dict comprehensions/literals (though it's
> true that there it's always inside brackets). And in lambdas –
> Here's code that is legal today (though not very practical):
>      while lambda: True:
>          break
> * There's supposed to be only one obvious way to do it! We alredy have .items()!
> I don't think this stops us from adding a new way of doing things which
> is more obvious than the old, and which should become the one way.
> After all, you don't say "for key in mapping.keys():", even though
> the keys() method exists.
You just might, if you modified the dictionary in the loop body, and you 
wanted to process the original list of keys but didn't need to remember 
the original values and wanted to avoid the overhead of copying the values.
> * What exactly would it do?
> There are multiple options —
> - loop over .keys() and use __getitem__ each time, like the
>    dict() constructor?
> - loop over .items(), like most of the code used today?
> - become a well-specified "key/value iteration protocol" with
>    __iteritems__() and its own bytecode operation?
> — but here I'm asking if building this bikeshed sounds useful, rather
> than what paint to buy.
I like it!  It seems so intuitive that, like Sven, I wonder why it's not 
already in the language.

As far as I can see it doesn't introduce any ambiguities.  I am thinking 
of code such as
     for k,j : x,(y,z), in complicated_expression:
I would guess (from a position of complete ignorance) that there would 
be no *insuperable* difficulty in parsing this.

I suggest (without feeling strongly about it) that optional parentheses 
should be allowed for stylistic reasons, i.e.
     for ( k : v ) in a_dict:
[I thought about
     for { k : v } in a_dict:
  before I realised that this is currently legal, albeit (probably) 
nonsensical, syntax.  [Python 2.7.3]]

One downside: Whatever implementation is chosen, it will not be "the one 
obvious way to do it".
E.g. an .iteritems()-like implementation will fail if the dictionary is 
modified during the loop.
         an .items()-like implementation will be expensive on a huge 
As there are already several ways of iterating over a dictionary, I 
think the new construct should be semantically equivalent to one of the 
existing ways, so that we don't have yet another behaviour to learn.  My 
bikeshed colour is that it be equivalent to using .items(), as I think 
this is least likely to trip up newbies (it won't raise an error if the 
dictionary is modified); YMMV.

Rob Cliffe
> That said, I do have a proof of concept implementation of the second
> option, in case you'd like to play around with this:
> Github: https://github.com/encukou/cpython/tree/keyval-iteration
> patch: https://github.com/encukou/cpython/commit/b9b0d973342280f0ef52e26a4b67f326ece82a54.patch
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
> -----
> No virus found in this message.
> Checked by AVG - www.avg.com
> Version: 2014.0.4821 / Virus Database: 4365/10312 - Release Date: 07/26/15

More information about the Python-ideas mailing list