> On Apr 29, 2020, at 12:55 AM, Tom Forbes <t...@tomforb.es> wrote: > > Hey Raymond, > Thanks for your input here! A new method wouldn’t be worth adding purely for > performance reasons then, but there is still an issue around semantics and > locking.
Right. > it doesn’t actually ensure the function is called once. Let's be precise about this. The lru_cache() logic is: 1) if the function has already been called and result is known, return the prior result :-) 2) call the underlying function 3) add the question/answer pair to the cache dict. You are correct that a lru_cache() wrapped function can be called more than once if before step three happens, the wrapped function is called again, either by another thread or by a reentrant call. This is by design and means that lru_cache() can be wrapped around almost anything, reentrant or not. Also calls to lru_cache() don't block across the function call, nor do they fail because another call is in progress. This makes lru_cache() easy to use and reliable, but it does allow the possibility that the function is called more than once. The call_once() decorator would need different logic: 1) if the function has already been called and result is known, return the prior result :-) 2) if function has already been called, but the result is not yet known, either block or fail :-( 3) call the function, this cannot be reentrant :-( 4) record the result for future calls. The good news is that call_once() can guarantee the function will not be called more than once. The bad news is that task switches during step three will either get blocked for the duration of the function call or they will need to raise an exception. Likewise, it would be a mistake use call_once() when reentrancy is possible. > The reason I bring this up is that I’ve seen several ad-hoc `call_once` > implementations recently, and creating one is surprisingly complex for > someone who’s not that experienced with Python. Would it fair to describe call_once() like this? call_once() is just like lru_cache() but: 1) guarantees that a function never gets called more than once 2) will block or fail if a thread-switch happens during a call 3) only works for functions that take zero arguments 4) only works for functions that can never be reentrant 5) cannot make the one call guarantee across multiple processes 6) does not have instrumentation for number of hits 7) does not have a clearing or reset mechanism Raymond _______________________________________________ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/CTAGWXD7WRU3NAHLP5IZ75PM2E3TQTG2/ Code of Conduct: http://python.org/psf/codeofconduct/