Strange behavior when passing a function as second parameter of the `setdefault` dictionary method

Question:

I don’t understand the behavior of setdefault in this scenario:

def f(x):
    return x+1

dct = {5: 15}

print(dct.setdefault(5, f(5)))

The key 5 is in the dictionary, but instead of returning the value 15 immediately, it wastes time computing the function at the second argument. In the end, it discards the output of f and returns 15.

Is this a bug? What is its purpose?

Asked By: s1m0n3

||

Answers:

Python allows you to use expressions as parameters to a function. In fact, you could view all parameters as expressions. Python will evaluate all of the parameter expressions from left to right, resolving each to a single object. A function object is created, the list is expanded into the parameter set for the function, and finally the function is called.

In dct.setdefault(5, f(5)), python has no idea whether a function parameter expression will be used or not. And it can’t evaluate the expression after the call is made. So, f(5) is resolved and the function is called.

If a function is expensive, then setdefault is not the tool for you. Use "not in" instead.

if 5 not in dct:
    dct[5] = f(5)
Answered By: tdelaney

In Python all arguments must be evaluated before the function is called. It would be a ‘performant’ behavior for this case, but could lead to consistency issues for others.

Answered By: Juan Federico