[PATCH 2 of 8] py3: switch from .iteritems() to .items() in mercurial/revset.py

Martijn Pieters mj at zopatista.com
Mon May 16 11:08:09 EDT 2016


On 16 May 2016 at 01:36, Pulkit Goyal <7895pulkit at gmail.com> wrote:
> Python 3.5 no longer supports dict.iteritems(), instead it has dict.items() which is also supported by Py2.
> Although the implementation in both the versions is different, but it works fine.

Yes, the end result is the same. However, their memory footprint and
performance characteristics are not the same.

In Python 2, `dict.items()` produces a new list with `(key, value)`
tuples, Python 3 produces a dictionary view object, which is just a
proxy that produces `(key, value)` tuples only when iterated over, on
the fly.

For small dictionaries in non-critical sections, that's probably fine.
But where a dictionary is *large*, you really want to stick to the
dict view approach, or use the `dict.iteritems()` approach (where the
Python 3 equivalent is `iter(dict.items())`, so can only be iterated
over once). In that case helper-functions are needed:

    if hasattr(dict, 'iteritems'):
        def iteritems(d):
            return d.iteritems()
    else:
        def iteritems(d):
            return iter(d.items())

for the iterating-once case or:

    from operator import methodcaller

    # using methodcaller avoids having to create another Python call frame.
    if hasattr(dict, 'viewitems'):
        viewitems = methodcaller('viewitems')
    else:
        viewitems = methodcaller('items')

if iteration more than once of dict set operations are needed. I don't
think we need a items-as-list case; that can be solved with
`list(d.items())` for both Python versions if you do find such a use.

Then use

    for name, func in iteritems(registrarobj._table):

This is where `six` comes in handy, which provides the exact two
functions I propose above.

-- 
Martijn Pieters


More information about the Mercurial-devel mailing list