Account imageLoginSign UpAccount image
Loading votes....
Save Question

Why does my Python function remember previous calls when I use a list as a default argument?

clock icon

asked 3 months ago

Message icon

1

Eye icon

3

1def add_item(item, my_list=[]):
2 my_list.append(item)
3 return my_list
4
5print(add_item(1)) # [1]
6print(add_item(2)) # [1, 2] Why not [2]?
7print(add_item(3)) # [1, 2, 3]
1def add_item(item, my_list=[]):
2 my_list.append(item)
3 return my_list
4
5print(add_item(1)) # [1]
6print(add_item(2)) # [1, 2] Why not [2]?
7print(add_item(3)) # [1, 2, 3]

I expected each call to start with an empty list. Why doesn't it work this way?

1 Answer

Default Argument Values in Python

The Issue with Mutable Default Arguments

You've encountered a common gotcha in Python: default argument values are evaluated only once at the point of function definition in the defining scope. This means that if you use a mutable default argument and mutate it, you will and have mutated that object for all future calls to the function as well.

Your Example

1def add_item(item, my_list=[]):
2 my_list.append(item)
3 return my_list
4
5print(add_item(1)) # [1]
6print(add_item(2)) # [1, 2]
7print(add_item(3)) # [1, 2, 3]
1def add_item(item, my_list=[]):
2 my_list.append(item)
3 return my_list
4
5print(add_item(1)) # [1]
6print(add_item(2)) # [1, 2]
7print(add_item(3)) # [1, 2, 3]

In this case, my_list is a list that's created when the function is defined, and the same list is used for all function calls.

Why This Happens

  • Default argument values are evaluated once at the point of function definition.
  • The default value for my_list is a mutable object (a list).
  • Each time you call add_item, you're appending to the same list object.

The Solution

To avoid this issue, you can use None as the default argument value and create the list inside the function:

1def add_item(item, my_list=None):
2 if my_list is None:
3 my_list = []
4 my_list.append(item)
5 return my_list
6
7print(add_item(1)) # [1]
8print(add_item(2)) # [2]
9print(add_item(3)) # [3]
1def add_item(item, my_list=None):
2 if my_list is None:
3 my_list = []
4 my_list.append(item)
5 return my_list
6
7print(add_item(1)) # [1]
8print(add_item(2)) # [2]
9print(add_item(3)) # [3]

Alternatively, you can also use a more concise version:

1def add_item(item, my_list=None):
2 my_list = my_list or []
3 my_list.append(item)
4 return my_list
1def add_item(item, my_list=None):
2 my_list = my_list or []
3 my_list.append(item)
4 return my_list

By doing this, you ensure that a new list is created for each function call, and you avoid the issue of the function "remembering" previous calls.

1

Write your answer here

Top Questions