Ethan Furman schreef op 16/12/2020 om 17:59:
Or, if the computationally massively expensive call uses potentially
different arguments for each invocation:

      some_var = d.get('a') or cme(arg1, arg2, ...)

I don't like that because it is very fragile: the expression will evaluate to the second part not only when 'a' is not in the dictionary but also whenever the value corresponding to key 'a' is false-y.

Example:

    def slow_function(a, b):
        # Pretend this is slow, or there is any other reason for this
        # function to be called only when strictly necessary.
        print('slow_function called')
        return a + b

    d = {
        'spam': 0,
        'ham': 1,
        'parrot': 2,
    }

    some_var = d.get('spam') or slow_function(31, 11)
    print(some_var)

Result: slow_function is called, and some_var equals 42 instead of 0.

You could make it work reliable by using a unique sentinel value and the walrus operator:

    SENTINEL = object()
    some_var = (
        r
        if (r := d.get('spam', SENTINEL)) is not SENTINEL
        else slow_function(31, 11)
        )

But I don't like that either because it's way too complicated.

What could be useful in some use cases, I think, is a wrapper function that evaluates the function lazily:

    def dict_get_lazily(d, key, fnc, *args, **kwargs):
        try:
            return d[key]
        except KeyError:
            return fnc(*args, **kwargs)

    some_var = dict_get_lazily(d, 'spam', some_function, 31, 11)



--
"Honest criticism is hard to take, particularly from a relative, a
friend, an acquaintance, or a stranger."
        -- Franklin P. Jones

Roel Schroeven

--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to