When you define a function with a default argument, the function uses that default values for that argument if it is not supplied. So in the case of append(5)
, to
is not specified, so the function assumes the value of to
to be None
- it's effectively the same as calling append(5, None)
.
So now, the function checks if to is None
, which it is, so to
gets reassigned to an empty list. 5
gets appended to the list, and the list is returned.
When you make the second call append(3)
, it is again as if you called append(3, None)
. Again, the if to is None
evaluates to True
, and to
is reassigned to an empty list. Then, 3
is appended to that empty list, and the list is returned.
Since the default argument (in this case None
) is immutable, the operations on to
do not persist the end of the function call. The function has its own chunk of memory which gets cleared when the function returns.
However, if the default argument was mutable (like for instance []
), that value is created when the function is defined (i.e. when python sees def func(arg1, arg2=[])
, it creates an empty list in memory and uses that list every time this function is called). Thus, any changes made to that list will persist the end of the function, since that mutable default argument was created when the function was defined (before the function was ever called).