1

In the following function L stores the values during every call.

For example, if I call f(1), L is now [1]. When I call it again the previous L is appended with the new value. So now L is [1,1].

def f(a, L=[]):

    L.append(a)
    return L

But in this function:

i = 5

def f(arg=i):

    print arg
i = 6

No matter how many times I call this function, the argument is still 5 - it does not remain updated between calls.

What is the reason why this does not get updated but the list does?

Patashu
  • 21,443
  • 3
  • 45
  • 53
subha
  • 161
  • 1
  • 7
  • 1
    related: [“Least Astonishment” in Python: The Mutable Default Argument](http://stackoverflow.com/q/1132941/4279) – jfs May 09 '13 at 01:29

2 Answers2

4

This is a good question. The reason why this happens is because the default arguments to functions are stored as single objects in memory, not recreated every time you call the function.

So when you have a list [] as a default argument, there will only be one list forever for the duration of that program. So when you add to the list you are adding to that one copy of the list. This is still true for numbers like 5. However, numbers are immutable in Python, and so when you alter a default argument that starts at a number, you're really making it point to a new number and not editing that 5 object, whereas many operations on lists mutate the list in place rather than returning a new list.

http://docs.python.org/3/tutorial/controlflow.html#default-argument-values

Important warning: The default value is evaluated only once. This makes a difference when the default is a mutable object such as a list, dictionary, or instances of most classes.

The recommended solution, if you need the behaviour of an empty list default argument without having the same empty list default argument every call to the function, is to do this:

def f(a, L = None):

    if L is None:
        L = []
    L.append(a)
    return L

The creation of an empty list is now evaluated on individual calls to the function - not once.

Patashu
  • 21,443
  • 3
  • 45
  • 53
  • This gives a lot of headaches while solving leetcode (or similar) problems when they run multiple test cases on the function. Python behaves differently than javascript. In JS, the default variables get reassigned everytime as soon as they are not supplied. – Ramsudharsan Manoharan Nov 18 '22 at 17:03
1

a.append() is different from i = 6. The first changes the array but the array stays the same object (the same but not equal). The latter on the other hand assigns a totally new value to a variable. It does not change any object (ints aren't mutable anyway).

Alfe
  • 56,346
  • 20
  • 107
  • 159