1

according to the doc, the get method of a dict can have two argument: key and a value to return if that key is not in the dict. However, when the second argument is a function, it'll run regardless of whether the key is in the dict or not:

def foo():
    print('foo')

params={'a':1}
print(params.get('a', foo()))
# foo
# 1

As shown above, the key a is in the dict, but foo() still runs. What happens here?

Sam-gege
  • 723
  • 3
  • 12
  • 2
    You call the function _before_ calling the get method, to get the _value_ to pass as a parameter. [`dict.get`](https://docs.python.org/3/library/stdtypes.html#dict.get) doesn't call a function if it's passed as a default anyway, you'd just get the function itself back. – jonrsharpe Apr 08 '23 at 17:08

2 Answers2

2

This is a common misconception, the arguments must be evaluated whether or not they are used by the function, for example:

>>> def f(x, y, z): pass
... 
>>> f(print(1), print(2), print(3))
1
2
3

So the print(1), print(2), print(3) statements are executed even if the function f does not use the arguments. You can use try except instead to evaluate foo() only when it is needed:

try:
    x = params['a']
except KeyError:
    x = foo()
Caridorc
  • 6,222
  • 2
  • 31
  • 46
-1
params.get('a', foo())

Your second argument is not a function, it's a function call. So the .get() method calls it to obtain its second argument.

To put your function as a second argument, you have to remove parenthesis after it:

params.get('a', foo)
MarianD
  • 13,096
  • 12
  • 42
  • 54
  • No, the `get()` method doesn't call it. It's called before `get()` is called. And removing the parentheses won't help since then we'd get the function as default value, instead of the return value of the function. – mkrieger1 Apr 08 '23 at 17:18
  • @mkrieger1, IMHO it's only an academic detail —the method `.get()`, seeing that its argument is not evaluated, **caused** its evaluation. – MarianD Apr 08 '23 at 17:22
  • @mkrieger1 - it's not my proposed solution, it's **your** understanding of my answer. The second form I wrote only to show the difference between using a *function call* and a *function itself*. – MarianD Apr 08 '23 at 17:25