[Python-3000] have iter(mapping) generate (key, value) pairs

Steven Bethard steven.bethard at gmail.com
Fri Jun 2 22:50:30 CEST 2006


I'd like to suggest that we (at least briefly) re-consider the
decision that iterating over a mapping generates the keys, not the
(key, value) pairs.  This was addressed somewhat in `PEP 234`_, with
the pros and cons basically being:

* From a purity standpoint, iterating over keys keeps the symmetry
between ``if x in y`` and ``for x in y``
* From a practicality standpoint, iterating over keys means that most
of the time, you'll also have to do a ``mapping[key]``, since most
iterations access both the keys and values.

I only bring this up now because Python 3000 is our opportunity to
review old decisions, and I think there's one more argument for
iterating over (key, value) pairs that was not discussed.  Iterating
over (key, value) pairs allows functions like dict() and dict.update()
to accept both mappings and (key, value) iterables, without having to
check for a .keys() function.  Just to clarify the point, here's the
code in UserDict.DictMixin::

    def update(self, other=None, **kwargs):
        # Make progressively weaker assumptions about "other"
        if other is None:
            pass
        elif hasattr(other, 'iteritems'):  # iteritems saves memory and lookups
            for k, v in other.iteritems():
                self[k] = v
        elif hasattr(other, 'keys'):
            for k in other.keys():
                self[k] = other[k]
        else:
            for k, v in other:
                self[k] = v
        if kwargs:
            self.update(kwargs)

Note that even though the `Language Reference`_ defines mappings in
terms of __len__, __getitem__, __setitem__, __delitem__ and __iter__,
UserDict.DictMixin.update has to assume that all mappings have a
.keys() method.

For comparison, here's what it would look like if mappings iterated
over (key, value) pairs::

    def update(self, other=None, **kwargs):
        if other is not None:
            for k, v in other:
                self[k] = v
        if kwargs:
            self.update(kwargs)

As far as backwards compatibility is concerned, if you need to write
code that works in both Python 2.X and Python 3000, you just need to
be explicit, e.g. using dict.iteritems() or dict.iterkeys() as
necessary.  (Yes, I know that .iter* is going to be dropped, but
that's a backward compatibility concern for another PEP, not this
one.)


.. _PEP 234:http://www.python.org/dev/peps/pep-0234/
.. _Language Reference: http://docs.python.org/ref/sequence-types.html

STeVe
-- 
Grammar am for people who can't think for myself.
        --- Bucky Katt, Get Fuzzy


More information about the Python-3000 mailing list