On May 8, 2020, at 20:36, Dan Sommers <2qdxy4rzwzuui...@potatochowder.com> wrote: > > On Fri, 8 May 2020 17:40:31 -0700 > Andrew Barnert via Python-ideas <python-ideas@python.org> wrote: > >> So, the OP is right that (1,2,3)==[1,2,3] would sometimes be handy, >> the opponents are right that it would often be misleading, and the >> question isn’t which one is right ... > > That's a good summary. Thank you. :-) > >> [1] If anyone still wants to argue that using a tuple as a hashable >> sequence instead of an anonymous struct is wrong, how would you change >> this excerpt of code: >> >> memomean = memoize(mean, key=tuple) >> def player_stats(player): >> # … >> … = memomean(player.scores) … >> # … >> >> Player.scores is a list of ints, and a new one is appended after each >> match, so a list is clearly the right thing. But you can’t use a list >> as a cache key. You need a hashable sequence of the same values. And >> the way to spell that in Python is tuple. > > Very clever.
I don’t think it’s particularly clever. And that’s fine—using common idioms usually is one of the least clever ways to do something out of the infinite number of possible ways. Because being intuitively the one obvious way tends to be important to becoming an idiom, and it tends to run counter to being clever. (Being concise, using well-tested code, and being efficient are also often important, but being clever doesn’t automatically give you any of those.) > Then again, it wouldn't be python-ideas if it were that > simple! "hashable sequence of the same values" is too strict. I think > all memoize needs is a key function such that if x != y, then key(x) != > key(y). Well, it does have to be hashable. (Unless you’re proposing to also replace the dict with an alist or something?) I suppose it only needs to be a hashable _encoding_ of a sequence of the same values, but surely the simplest encoding of a sequence is the sequence itself, so, unless “hashable sequence” is impossible (which it obviously isn’t), who cares? > def key(scores): > ','.join(str(-score * 42) for score in scores) This is still a sequence. If you really want to get clever, why not: def key(scores): return sum(prime**score for prime, score in zip(calcprimes(), scores)) But this just demonstrates why you don’t really want to get clever. It’s more code to write, read, and debug than tuple, easier to get wrong, harder to understand, and almost certainly slower, and the only advantage is that it deliberately avoids meeting a requirement that we technically didn’t need but got for free. > Oh, wait, even that's too strict. All memoize really needs is if > mean(x) != mean(y), then key(x) != key(y): > > memomean = memoize(mean, key=mean) > def player_stats(player): > # … > … = memomean(player.scores) … > # … Well, it seems pretty unlikely that calculating the mean to use it as a cache key will be more efficient than just calculating the mean, but hey, if you’ve got benchmarks, benchmarks always win. :) (In fact, I predicted that memoizing here would be a waste of time in the first place, because the only players likely to have equal score lists to earlier players would be the ones with really short lists—but someone wanted to try it anyway, and he was able to show that it did speed up the script on our test data set by something like 10%. Not nearly as much as he’d hoped, but still enough that it was hard to argue against keeping it.) _______________________________________________ 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/QLEDJ7XBE3EHG2C3J2QEFOWROSTMSH4C/ Code of Conduct: http://python.org/psf/codeofconduct/