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

Terry Reedy tjreedy at udel.edu
Mon Jul 27 23:48:21 CEST 2015

```On 7/27/2015 3:17 PM, Steven D'Aprano wrote:
> On Tue, Jul 28, 2015 at 02:25:00AM +1000, Chris Angelico wrote:
>
>> What my suggestion was positing was not so much DWIM as "iterate over
>> the keys and values of anything". A mapping type has a concept of keys
>> and values; an indexable sequence (list, tuple, etc) uses sequential
>> numbers as indices and its members as values.
> .............^^^^^^^
>
>
> Keys and indices are not the same thing, and Python is not Lua.

Both sequences and dicts can be viewed and used as functions over a
finite domain. This is pretty common. If one does, *then* the keys and
indices serve the same role as inputs.

> While there are certain similarities between the indices of a sequence
> and the keys of a mapping, they really don't play the same role in any
> meaningful sense.

If one uses lists or dicts to implement functions as sets with efficient
access, then indecex/keys both play the same role as inputs.  In
general, keys/indexes are both efficient means to retrieve objects. The
access issue is precisely why we use dicts more that sets.

> Consider:

> x in mapping  # looks for a key x
> x in sequence  # looks for a value x, not an index ("key") x

For a function, 'in' looks for an input/output pair, so both the above
are wrong for this usage.

> Consider this too:
>
> mapping = {i:i**2 for i in range(1000)}
> sequence = [i**2 for i in range(1000)]

Construct a function as 'set' by adding one pair at a time.

> for obj in (mapping, sequence):
>     while 0 in obj.keys():
>         del obj[0]

Deleting a pair from a function is a dubious operation.

>     assert 0 not in obj.keys()

> The first problem is that lists don't have a keys() method. But that's
> okay, pretend that we've added one. Now your problems have only begun:
>
> len(mapping)  # returns 1000-1
> len(sequence)  # returns 0
>
> Well that sucks.

Right.  If deletion *is* allowed, then it must be limited to .pop() for
list implementations of functions.

> Despite the apparent analogy of key <=> index, it's remarkable hard to
> think of any practical use for such a thing. I cannot think of any time
> I have wanted to, or might want to in the future, ducktype lists as
> dicts, with the indices treated as keys.

Python already ducktypes list/dict and index/key by using the same
subscript notation and corresponding special methods for both.  Because
of this, it is possible to write algorithm that work with both a list
(or list of lists) and a dict or DefaultDict or subset of either.

> Apart from practical problems such as the above, there's also a
> conceptual problem.

We seem to have different ideas of 'practical' versus 'conceptual'.

> Keys of a mapping are *intrinsic* properties of the mapping.

To me, this is as least in part a practical implementation issue.  In a
function, keys are intrinsically part of pairs.  For a dict in general,
they are not necessarily intrinsic properties of the values.  In a
unique. There is no sense in which the objects are functionally derived
from the names.

> But indices of a sequence are *extrinsic* properties.

Once the first item is given an index, the rest of the indexes follow.
If the items are functionally derived from the indexes, then even the
first index is not arbitrary.

In spite of everything above, I am pretty dubious about adding x:y as an
iteration target: I have no problem with mapping.items() and
enumerate(iterable).

--
Terry Jan Reedy

```