+ 3

The hidden trap in python function

What will be the output of the following Python code? def func(a, b=[]): b.append(a) return b print(func(1)) print(func(2)) print(func(3, [])) print(func(4))

21st Feb 2025, 9:53 AM
Mira Wadhwa
Mira Wadhwa - avatar
12 Respostas
+ 5
b is a list Variable a keeps moving to the list print(func(3,[])) Here, we're passing a new, empty list [] as the argument for b. This overrides the default argument. b becomes [3] but does not replace b list. https://sololearn.com/compiler-playground/ce0o4o5JlF0r/?ref=app
21st Feb 2025, 12:01 PM
BroFar
BroFar - avatar
+ 3
You can find out _what_ the output is by running the code on sololearn playground. _Why_ the output is like this, is a different question. Think about it like this: What does "b" refer to in each function call? What do you know about how Python handles lists?
21st Feb 2025, 11:14 AM
Lisa
Lisa - avatar
+ 3
BroFar Have a look at the last printed list. Consider letting func() return b, id(b), for instance.
21st Feb 2025, 3:40 PM
Lisa
Lisa - avatar
+ 3
I, too, am surprised by the result, because I expected the default parameter to be newly created in each call. I had Gemini explain it: "The behavior can be surprising and lead to unintended side effects if you're not aware of how default arguments work with mutable objects.  It violates the principle of least astonishment.  People often expect default arguments to be re-initialized each time the function is called, as is the case in many other programming languages. **Default Argument Evaluation:** Default arguments in Python functions are evaluated *only once*, when the function is defined, not each time the function is called." Well, now it makes sense.
21st Feb 2025, 6:51 PM
Brian
Brian - avatar
+ 2
Is this a quiz or a genuine question?
21st Feb 2025, 10:26 AM
Lisa
Lisa - avatar
+ 2
Lothar print(func(3, [])) # Third call. Here, you explicitly pass a new empty list. # ic| a: 3 # ic| b: [3] # [3]
21st Feb 2025, 3:24 PM
BroFar
BroFar - avatar
+ 1
Um im did not see that one
21st Feb 2025, 3:52 PM
Christian Francis
Christian Francis - avatar
0
A genuine question. Hoping answer with explanation
21st Feb 2025, 10:46 AM
Mira Wadhwa
Mira Wadhwa - avatar
0
Where is it i dont see it and i finished intro to phyton
21st Feb 2025, 6:52 PM
Christian Francis
Christian Francis - avatar
0
Brian I remember reading something about this behavior. https://inventwithpython.com/beyond/chapter8.html#calibre_link-174
22nd Feb 2025, 1:28 AM
Wong Hei Ming
Wong Hei Ming - avatar
0
def func(a, b=[]): Under behavior most people expect, the declaration of func would be evaluated at compile, and the evaluation of the default argument would be evaluated at execution. However the Python devs wanted to avoid split evaluation for function definitions with default arguments. Following one of the language goals, the devs wanted the entire line to be evaluated in one go meaning the default argument is also evaluated at compile. This only becomes a problem for MUTABLE default arguments, turning them into effectively static function variables folks are familiar with in other languages. To avoid this issue, the suggested work-around is def func(a, b=None): if b is None: b = [] b.append(a) return b None is IMMUTABLE. b = [] is not just updating the default argument, but completely replacing it since None can not be changed. So b will always start as None for every function call which relies on the default argument.
22nd Feb 2025, 2:58 AM
Shardis Wolfe
0
Wong Hei Ming great link 👍 Mira Wadhwa "Don’t Use Mutable Values for Default Arguments" Also be careful when passing mutable values into arguments. Because they are cached in memory and acts like global variables. do this instead: def func(a, b=None): if b is None: b = [] # assign b here instead b.append(a) return b print(func(1)) print(func(2)) print(func(3, [])) print(func(4)) print(func(7, [5,6]))
22nd Feb 2025, 3:04 AM
Bob_Li
Bob_Li - avatar