The temptation to insist "see, YAGNI!" at this point I shall resist.

*You* might not need it, but I've seen it come up a lot on Stack Overflow, and all too often people end up going for the much less efficient solution. I personally have also written code with practical applications using `next(iter(mydict))`.

I was +0 sympathetic to that until you posted this obvious extension
of the idea

I don't see these dict methods as an "obvious extension" of the idea; I see them as unneeded/irrelevant *if* a more general way of doing this is added to itertools.

That's an awful lot of new methods to take advantage of what for many
applications of dict (in fact, *all* of my applications ever[1]) is an
irrelevant ordering.

I agree that it's a lot of methods to add. That's precisely why I prefer Inada Naoki's suggestion of additions to itertools, and why I've never bothered starting a thread on the subject myself. But since the topic was being discussed after Erik started this thread, I thought I might mention the alternative solution that's been in the back of my head for a while.

[A]nyone who wants it can do it themselves:

As I said in my previous message, the existing idiom (`next(iter(mydict))`) appears to be extremely non-obvious for beginners in Python, causing them to often go for much more inefficient options. No one is claiming "there is no way to do this" at present; the argument is that the best way to do this is, at present, *not sufficiently obvious*.

These defs do something undefined on unordered mappings (ie, not based
on dict), and may be dangerous in that sense.

Excellent point (though note that my suggestion was to extend the dict interface, not the interface for all mappings).

In the current implementation, positional indexing is time-expensive

Yes, that's exactly why I don't support Erik's original suggestion of positional indexing for dict.keys(), dict.values() and dict.items(), and why I *only* support easy ways of fetching the first/last object from the view.

I wonder if any code is being written obscurely to ensure that
keys get added to dicts in the "right" order

I personally have used dictionaries as ordered sets in the past (skip to the last code snippet in this answer: https://codereview.stackexchange.com/a/264437/24517), and would object to this being called an "obscure" use of the data structure. It is, by now, both well-known and well-advertised in the documentation that dictionaries are guaranteed to maintain insertion order. It's obviously not how the data structure has historically been used, but I don't see how that makes it an invalid use of the data structure *now*. Why shouldn't users be expected to exploit an advertised feature of the language?

On 6 Oct 2021, at 10:29, Stephen J. Turnbull <stephenjturnbull@gmail.com> wrote:

Alex Waygood writes:

Whereas obviously,

The temptation to insist "see, YAGNI!" at this point I shall resist.

a much better way (especially if it's a very large dictionary) is
to do:

      first_key = next(iter(mydict))

[Inada Naoki]
I think we can add `itertools.first()` for this idiom, and
`itertools.last()` for `next(iter(reversed(x)))` idiom.

I was +0 sympathetic to that until you posted this obvious extension
of the idea:

I like this idea, a lot. Another possibility I've been wondering
about was whether several methods should be added to the dict
interface:
dict.first_key = lambda self: next(iter(self))
dict.first_val = lambda self: next(iter(self.values()))
dict.first_item = lambda self: next(iter(self.items()))
dict.last_key = lambda self: next(reversed(self))
dict.last_val = lambda self: next(reversed(self.values()))
dict.last_item = lambda self: next(reversed(self.items()))

That's an awful lot of new methods to take advantage of what for many
applications of dict (in fact, *all* of my applications ever[1]) is an
irrelevant ordering.

And anyone who wants it can do it themselves:

def first_key(dct): return next(iter(dct))
def first_val(dct): return next(iter(dct.values()))
def first_item(dct): return next(iter(dct.items()))
def last_key(dct): return next(reversed(iter(dct)))
def last_val(dct): return next(reversed(iter(dct.values())))
def last_item(dct): return next(reversed(iter(dct.items())))

These defs do something undefined on unordered mappings (ie, not based
on dict), and may be dangerous in that sense.  OTOH, I suspect the
methods will do the wrong thing with many ordered mappings based on
dict that support orders other than insertion order.

But I think I like a lot more the idea of adding general ways of
doing these things to itertools.

If you want to convince others, you really need to be more specific
about the requirements that lead you to this conclusion.  In the
current implementation, positional indexing is time-expensive, much
more so than keeping an auxiliary list and using dct[lst[ndx]].  It
could also allow timing attacks if used in security-sensitive code.
And I wonder if any code is being written obscurely to ensure that
keys get added to dicts in the "right" order, instead of keeping an
explict, efficient, and reorderable auxiliary list of keys?

Footnotes:
[1]  It's true that some code I import is probably improved because
the developers don't waste time tracking down test failures in dict-
based data structures. :-)