[Python-ideas] OrderedDict.peekitem()

Oscar Benjamin oscar.j.benjamin at gmail.com
Tue Jul 7 16:35:47 CEST 2015

On Tue, 7 Jul 2015 at 13:34 Steven D'Aprano <steve at pearwood.info> wrote:

> On Tue, Jul 07, 2015 at 12:59:07AM -0700, Kale Kundert wrote:
> > 3. Readability counts, and those expressions hide the intent of the
> programmer.
> >  You wouldn't use 'next(iter(o))' to access the first element of a list,
> because
> > that would be confusing and obfuscated.
> I agree with all of those objections, especially the third. Which is why
> the reasonable and simple solution is to write:
> def first(od):
>     return next(iter(od))
> def last(od):
>     return next(reversed(od))
> then call first(o), last(o). Add comments, documentation and tests to
> taste. Or subclass OrderedDict and add first() last() methods.

If the OrderedDict is empty both of the above will raise StopIteration.
This can have unintended consequences if the OrderedDict is called from
another iterator/generator etc. So it should probably be:

def first(od):
        return next(iter(od))
    except StopIteration:
        raise KeyError

> I am unconvinced that peeking at the first and last items of a dict
> (ordered, sorted or otherwise), let alone O(1) indexed access to items,
> is a good fit for the OrderedDict API. If I were the OD maintainer, I
> would want to understand your use-case (why are you using an OD as a
> queue, instead of a list, deque, or queue?), and possibly hear two or
> three additional uses, before agreeing to add it to the API.

I once wanted to be able to peek the last item. My usecase was something to
do with traversing a graph. Perhaps a depth-first search where I wanted a
stack of the vertices I was traversing and an efficient way to check for a
vertex in the stack (to avoid traversing cycles). I think the keys were the
vertices and the values were iterators over the neighbours of the
corresponding vertices.

After traversing all neighbours of a vertex I want to pop that vertex off
and continue traversing the vertex preceding it on the stack. I can
retrieve the vertex from the top of the stack with popitem. However I want
the returned vertex to remain in the stack while traversing its other
neighbours so I pop it off and then push it back on again akin to:

def peekitem(od):
    key, val = od.popitem()
    od[key] = val
    return key, val

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20150707/2c9e49a3/attachment.html>

More information about the Python-ideas mailing list