On Tue, 7 Jul 2015 at 13:34 Steven D'Aprano <steve@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):
    try:
        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

--
Oscar