> 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 <stephenjturnb...@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. :-)
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/GPPMS36S6XCN63ZIF64FLG7UQHFDXO5F/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to