[Python-Dev] PEP 469: Restoring the iterkeys/values/items() methods

Steven D'Aprano steve at pearwood.info
Sat Apr 19 06:25:53 CEST 2014


On Fri, Apr 18, 2014 at 10:31:29PM -0400, Nick Coghlan wrote:
> After spending some time talking to the folks at the PyCon Twisted
> sprints, they persuaded me that adding back the iterkeys/values/items
> methods for mapping objects would be a nice way to eliminate a key
> porting hassle for them (and likely others), without significantly
> increasing the complexity of Python 3.

It would also considerable add to the cruft of Python 3. One motive for 
going through the pain of Python 2 to 3 migration was to remove cruft. 
Adding it back in again is not just an aid to porting but actively 
making Python 3 a worse (well, "less better") experience.

In the case of u'' syntax for strings, that was (somewhat) unavoidable, 
as you get a syntax error in Python 3 otherwise. So you cannot write:

    if sys.version < "3":
        s = u"êπд"
    else:
        s = "êπд"

it simply doesn't work. But you can write:

    if sys.version < "3":
        items = mydict.iteritems()  # or viewitems
    else:
        items = mydict.items()

Feature discovery is better than explicit version checks:

    try:
        items = mydict.iteritems()
    except AttributeError:
        items = mydict.items()


In my experience, writing polyglot 2+3 code can be easily handled with a 
few helper functions, which is not the case with unicode string 
literals. (Non-polygot code of course can just use the methods 
directly.) I don't see this is a problem to be solved, or even much of a 
nuisance. Polyglot code is never going to be quite as straightforward or 
idiomic as non-polyglot code, and that's a good thing, as it reminds the 
reader that they are dealing with polyglot code.

So while I'm sympathetic to wanting to ease the 2/3 transition, even at 
the expense of re-introducing some cruft when unavoidable, I don't think 
that the difficulty of dealing with dict items|iteritems|viewitems etc. 
justifies re-adding cruft.


[...] 
> Rationale
> =========
> 
> Similar in spirit to PEP 414 (which restored explicit Unicode literal
> support in Python 3.3), this PEP is aimed primarily at helping users
> that currently feel punished for making use of a feature that needed to be
> requested explicitly in Python 2, but was effectively made the default
> behaviour in Python 3.

"Feel punished"? That's awfully strong language. It may even be true, in 
the sense that some people *feel* that they are being punished, but I 
think the barrier to doing something about that needs to be a bit 
higher, namely that they *actually are* being punished.

I think that if "write a helper function" is punishment, then nearly 
every programmer is being punished *all the time*. That's part of 
programming. And if every 2+3 helper is seen as punishment that needs to 
be reversed, then we'll end up with Python 3.5 or 3.6 being virtually 
the same as Python 2.7 only with a few extra features.


> Users of list-based iteration in Python 2 that aren't actually relying on
> those semantics get a free memory efficiency improvement when migrating to
> Python 3, and face no additional difficulties when migrating via the common
> subset of Python 2 and 3.
> 
> By contrast, users that actually want the increased efficiency may have
> faced a three phase migration process by the time they have fully migrated
> to Python 3:
> 
> * original migration to the iterator based APIs after they were added in
>   Python 2.2

That was a long time ago. Surely we're not counting new features 
introduced a decade ago as part of the cost of migrating to Python 3?


> * migration to a separate function based API in order to run in the common
>   subset of Python 2 and 3
> * eventual migration back to unprefixed method APIs when finally dropping
>   Python 2.7 support at some point in the future

I'm not actually seeing the problem here. Forget 2+3, what you've 
described is surely part of the process of dealing with nearly any 
multi-version code. Back when I was still writing code to support Python 
2.3 through 2.5, I had helper functions like this:

def sort(alist, key=None):
    if key is None:
        alist.sort()
    else:
        try:
            alist.sort(key=key)
        except TypeError:
            # Python too old. Use the DSU idiom.
            ...

When I dropped support for 2.3, I eventually (but not at first) moved 
back from sort(mylist) to mylist.sort(). I don't see that the situation 
with iterkeys etc. is terribly different.


> This PEP proposes to just eliminate all that annoyance by making the iterator
> based APIs work again in Python 3.5+. As with the restoration of Unicode
> literals, it does add a bit of additional noise to the definition of Python
> 3, but it does so while bringing a significant benefit in increasing the size
> of the common subset of Python 2 and Python 3 and so simplifying the process
> of migrating to Python 3 for affected Python 2 users.

To me, this feels more like re-adding cruft for trivial benefit. I would 
want to see justification for why this gives *significant* benefit 
before I could support it. As the PEP stands now, I'm -1. I might be 
persuaded to change to 0 if the dict.iter* methods were added and 
immediately deprecated, rather than sold as a positive feature to be 
added to the Mapping API.



-- 
Steven


More information about the Python-Dev mailing list