This is an interaction between two different things:
1) Function argument defaults in Python are not recalculated at each invocation, but at function definition time (bigger discussion at "Least Astonishment" and the Mutable Default Argument)
2) Python needs to evaluate all arguments to a function before it will call the function (e.g. to perform print(1+2, 5*3)
, 1+2
and 5*3
will need to be calculated before print
is even considered)
Thus, if you call f
multiple times without a second argument, it will just append to the same array you declared originally in the def
. This is what you can clearly see in the second example. The first invocation prints arr
after the first mutation ([1]
); the second prints arr
after the second one ([1, 2]
).
The first example is different because of the second principle I stated: all the parameters are evaluated before the function is called. So print(f(1), f(2))
will first invoke f(1)
, changing arr
to [1]
; then f(2)
will be evaluated, changing arr
to [1, 2]
. Since both function calls returned the reference to arr
, print
will then print the content of arr
twice: [1, 2], [1, 2]
.