Search code examples
pythondictionarydefault

Why is the default value always computed?


Let's say I have a dictionary d that has either a key 0 or a key 1. I want to assign to x the value d[0] if it exists and d[1] otherwise. I also want to destroy key 0 if it exists. I would write:

    x = d.pop(0,d[1])

But then running this for d = {0:'a'} raises an error.

Similarly, let's say I have a function that takes a keyword argument x. If x is computed already, then I want to use the value that is given. Otherwise, I need to compute it.

    import time
    def long_calculation():
        time.sleep(10)
        return 'waited'

    def func(**kwargs):
        x = kwargs.pop('x',long_calculation())
        return x

Running f(x='test') takes 10 seconds.

I could do something like

    x = kwargs.pop('x',None)
    if x is None:
        x = long_calculation()

But this is a bit cumbersome.


Solution

  • For caching function results, have a look at functools.lru_cache. Example:

    from functools import lru_cache
    @lru_cache(maxsize=32)
    def long_calculation():
        time.sleep(10)
        return 'waited'
    

    The second call returns the cached value:

    print(long_calculation()) # 10 seconds
    print(long_calculation()) # instant
    

    If you just want to short circuit dict.pop() I think it's more straightforward to just put it in nested try blocks. Like:

    try: 
        d.pop(0)
    except KeyError:
        try:
            d[1]
        except KeyError:
            <expensive value>