What happens when I reassign the mutable default argument inside a function?

Related searches

I know this has been answered in highly active 'least astonishment' question, I modified code snippet slightly but still don't understand why it produces new empty list and adds 1 to it..

def foo(var=[]):
    if len(var) == 0:
        var = []
    print(var)
    var.append(1)
    return var

print(foo())
print(foo())

outputs:

[]
[1]
[]
[1]

My expected logic of this python snippet:

  • on the first call of foo(), var is initialized to empty list and indeed - evaluated at definition of foo ONCE - as the popular question answered.

  • That if clause check should not be entered at all - because var is initialized only once, on the 2nd call foo() it should simply skip it and add 1 to var = [ 1 ] thus making the result [1,1] after the 2nd call.

But it does still go to if clause and init var to [] every time.. why?

However, if I remove the if clause:

def foo(var=[]):

    print(var)
    var.append(1)
    return var


print(foo())
print(foo())

It does append "1" to var every time and var grows:

[1]

[1,1]

So the if clause is entered and checked for validity.. confused about the execution..


Let's rewrite your example so that we make some change to the argument before reassigning:

In [262]: def foo(var=[]): 
     ...:     var.append(1)   # 1
     ...:     print(var)      # 2
     ...:     var = []        # 3
     ...:     return var      # 4
     ...:                                                                            

In [263]: foo()                                                                      
[1]
Out[263]: []

In [264]: foo()                                                                      
[1, 1]  # reflects the append from the previous call
Out[264]: []

The append step in line 1 mutates the default argument list. The reassignment step in line 3 simply reassigns the variable var to a new list (a completely different object), that's what you return.

You'll see each subsequent call modifies the default argument list, it's still there but you just don't see it because you lose the reference to it when you reassign.

I recommend reading this article by Ned Batchelder.

What happens when I reassign the mutable default argument inside , I know this has been answered in highly active 'least astonishment' question, I modified code snippet slightly but still don't understand why it� Python Mutable Function Arguments. Python mutable objects like dict and list are also passed by reference. If the value of a mutable object is changed inside the function block scope then its value is also changed inside the caller or main block scope regardless of the name of the argument.


alright, so the two things:

  1. var in your function definition is assigned to an empty list i.e [] that is good,
  2. var in the if statement is again being re-assigned but is the same thing, an empty list, this you don't really need as it's preventing you from achieving [1,1]

this may help clear things of why you're "expecting" a var = [1,1] the first time around:

 def foo(var=[]):
    if len(var) == 0:
       print(var)

    var.append(1)
    return var

print(foo()) # returns [],[1]

print(foo()) # returns  [1,1] this list appended another 1 in because when you ran this instance of foo, this list was not empty anymore rather filled with 1 and bypassed the if statement and appended another 1 resulting to [1,1]

thus, you don't really need that var = [] in the if statement as it confuses the next steps as to what you want to achieve...

hope that helps somewhat :)

Mutable Default Arguments in Python | by Prashant Sharma, A mutable object can change its state or… In this function, I set data to a list ( mutable object) as a default argument. This is happening because default argument values are stored in the function object and not the code� Good Use of Mutable Default Argument However, Mutable Default Argument have some good use-case also as following-1.Binding local variable to the current value of the outer variable in a callback 2.Cache/Memoization. I hope you like the explanation of Mutable Default Arguments in Python.


var=[] on line 1 gets evaluated once when the function is defined

var=[] on line 3 gets evaluated every time you pass a var with len(var) == 0, for instance when you pass no args and the default is used.

This means that the [] on line 3 is a new list every time the function is called, as that line of code is executed every time the function is called.

Mutable Default Arguments in Python - DEV, A mutable object can change its state or contents and immutable In the above function, I set data to a list(Mutable object) as a default argument. The reason why this is happening because default argument values are� It’s just a matter of avoiding using a mutable default value. A common way to create a new mutable object by default every time a function is called is to use an immutable placeholder value like None. The function looks for that placeholder value and, when found, replaces it with a brand new instance of the mutable type.


Python mutable default argument: Why?, In most cases you will have immutable default arguments and Python can construct If they went the other way, the lexical scope might change between the at function definition time, so you can't do that and instead have to do the clunky: Working of default arguments How default arguments work in C++. We can understand the working of default arguments from the image above: When temp() is called, both the default parameters are used by the function. When temp(6) is called, the first argument becomes 6 while the default value is used for the second parameter.


It just makes the local variable in the function body mutable. That is, you, can re-assign to the arguments of the function, or mutate them. I believe this doesn't actually show up in rustdoc itself, as it's actually not a part of the function signature. It's an implementation detail.


For every function call default argument values must be passed to the called function. If a default argument value contains side-effects, it is significant when those side effects are evaluated – once for the entire program (at parse time, compile time, or load time), or once per function call, at call time.