1

Here, the list is defined as a local variable in the parameter of the function foo, but I'm confused why even on repeated calls the list still remembers it's previous values, why is it acting like a static variable?

def foo(character,my_list = []):
    my_list.append(character)
    print(my_list)

foo("a")
foo('b')
foo('c')

---- Output ----

['a']
['a','b']
['a','b','c']
ansme
  • 413
  • 2
  • 11
  • 1
    because default arguments are evaluated *once* at function definition time. In a sense, you can think of them as static variables like C if that helps you remember it. – juanpa.arrivillaga May 20 '20 at 03:49
  • @juanpa.arrivillaga Okay! thanks, but btw if I ever wanted to achieve the functionality of a static variable then would it be alright to use this approach? – ansme May 20 '20 at 04:58
  • it wouldn't exactly be equivalent, because you can pass *any* object to that argument. – juanpa.arrivillaga May 20 '20 at 05:15
  • Check out [this question that I answered a while back](https://stackoverflow.com/questions/56811860/c-like-static-variable-inside-a-python-class-method/) on what you can do to have something like a C static variable (it's not going to be a perfect fit...) – juanpa.arrivillaga May 20 '20 at 05:16
  • @juanpa.arrivillaga okay thank you! – ansme May 20 '20 at 11:58

2 Answers2

3

When you define a mutable value as default argument, what python does is something like this:

default_list = []
def foo(character, my_list=default_list):
    my_list.append(character)

The same happens for any other mutable type (dict for instance). You can find a very detailed explanation here: https://docs.quantifiedcode.com/python-anti-patterns/correctness/mutable_default_value_as_argument.html

One way you can make an empty list as a default for a list can be:

def foo(character, my_list=None):
    if my_list is None:
        my_list = []
    my_list.append(character)
luigibertaco
  • 1,112
  • 5
  • 21
  • 2
    Well, it works this way *for all objects*, just it only really becomes an issue with mutable objects – juanpa.arrivillaga May 20 '20 at 03:48
  • 1
    It's true, and here is a very long discussion about this on StackOverflow https://stackoverflow.com/questions/1132941/least-astonishment-and-the-mutable-default-argument?noredirect=1&lq=1 – luigibertaco May 20 '20 at 03:59
2

This is one of the common gotchas:

Python’s default arguments are evaluated once when the function is defined, not each time the function is called (like it is in say, Ruby). 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.

adrtam
  • 6,991
  • 2
  • 12
  • 27