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/

Reply via email to