> On Apr 30, 2020, at 6:32 AM, Joao S. O. Bueno <jsbu...@python.org.br> wrote:
> 
> Of course this is meant to be something simple - so there are no "real
> world use cases" that are "wow, it could not have
> been done without it".

The proposed implementation does something risky, it hold holds a non-reentrant 
lock across a call to an arbitrary user-defined function.  The only reason to 
do so is to absolutely guarantee the function will never be called twice.  We 
really should look for some concrete examples that require that guarantee, and 
it would be nice to see how that guarantee is being implemented currently (it 
isn't obvious to me).

Also, most initialization functions I've encountered take at least one 
argument, so the proposed call_once() implementation wouldn't be usable at all. 

> I was one of the first to reply to this on
> "python-ideas", as I often need the pattern, but seldon
> worrying about rentrancy, or parallel calling. Most of the uses are
> just that: initalize a resource lazily, and just
> "lru_cache" could work. My first thought was for something more
> light-weight than lru_cache (and a friendlier
> name).

Right.  Those cases could be solved trivially if we added:

    call_once = lru_cache(maxsize=None)

which is lightweight, very fast, and has a clear name.  Further, it would work 
with multiple arguments and  would not fail if the underlying function turned 
out to be reentrant.

AFAICT, the *only* reason to not use the lru_cache() implementation is that in 
multithreaded code, it can't guarantee that the underlying function doesn't get 
called a second time while still executing the first time. If those are things 
you don't care about, then you don't need the proposed implementation; we can 
give you what you want by adding a single line to functools.

> So, one of the points I'd likely have used this is here:
> 
> https://github.com/jsbueno/terminedia/blob/d97976fb11ac54b527db4183497730883ba71515/terminedia/unicode.py#L30

Thanks — this is a nice example.  Here's what it tells us:

1) There exists at least one use case for a zero argument initialization 
function
2) Your current solution is trivially easy, clear, and fast.   "if CHAR_BASE: 
return".
3) This function returns None, so efforts by call_once() to block and await a 
result are wasted.
4) It would be inconsequential if this function were called twice.
5) A more common way to do this is to move the test into the lookup() function 
-- see below.


Raymond

-------------------------

CHAR_BASE = {}

def _init_chars():
    for code in range(0, 0x10ffff):
        char = chr(code)
        values = {}
        attrs = "name category east_asian_width"
        for attr in attrs.split():
            try:
                values[attr] = getattr(unicodedata, attr)(char)
            except ValueError:
                values[attr] = "undefined"
        CHAR_BASE[code] = Character(char, code, values["name"], 
values["category"], values["east_asian_width"])

def lookup(name_part, chars_only=False):
    if not CHAR_BASE:
      _init_chars()
    results = [char for char in CHAR_BASE.values() if re.search(name_part, 
char.name, re.IGNORECASE)]
    if not chars_only:
        return results
    return [char.char for char in results]
_______________________________________________
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/JZQLF5LXV47SJP6ZSTG27246S6OIYTPM/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to