Search code examples
pythondefault-parameters

When the function runs multiple times, the list is nested in the default parameter, but the integer is not


The list, x, isn't initialized to the parameter default value each time the function is operated, but remains in the previous state and adds a new value. That's how the function was executed 5 times, so it became [7, 7, 7, 7, 7]. However, the integer y appears to hold the default value. It has been run 5 times, but it continues to output 2. Why does y finally output 2 instead of 6 when the function is executed 5 times?

I've already read this question, but it explains where the list binds to a function. But I wonder why the principle does not apply to integer default parameters.

def foo(x=[],y=1):
    x.append(7)
    y += 1
    return x, y

print(foo())
print(foo())
print(foo())
print(foo())
print(foo())
([7], 2)
([7, 7], 2)
([7, 7, 7], 2)
([7, 7, 7, 7], 2)
([7, 7, 7, 7, 7], 2)

Solution

  • Int's are immutable, lists are not. When you assign a default value to a parameter you are assigning a reference to that value. Performing y += 1 actually creates a new reference and assigns it to y, it does not change the value of the old reference. When you mutate the container you are not changing the reference. Example:

    y = 1
    x = y
    
    # This will be true as they have the same reference
    print(x is y)  #  True
    
    y += 1
    # This will be false as the reference to y has been changed
    print(x is y)  #  False
    
    y = []
    x = y
    
    # This will be true as they have the same reference
    print(x is y)  #  True
    
    y.append(1)
    # This will still be true, the reference to the container remains the same.
    print(x is y)  #  True