Umang Gupta
Umang Gupta

Reputation: 16450

Functions with mutable default values

I am confused about python's evaluation of default function arguments. As mentioned in the documentation (https://docs.python.org/3.6/tutorial/controlflow.html#more-on-defining-functions)

def f(a, L=[]):
    L.append(a)
    return L

print(f(1))
print(f(2))
print(f(3))

results in

[1]
[1,2]
[1,2,3]

But

def f(a, L=[]):
    L = L+[a]
    return L 

print(f(1))
print(f(2))
print(f(3))

results in

[1]
[2] 
[3]

If L is evaluated only once, shouldn't both the function return the same result? Can someone explain what am I missing here?

This question is different than "Least Astonishment" and the Mutable Default Argument. That question is questioning the design choice while here I am trying to understand a specific case.

Upvotes: 3

Views: 105

Answers (2)

Ubdus Samad
Ubdus Samad

Reputation: 1215

You are not appending but sort of creating a new L here:

>>> def f(a, L=[]):
    L = L+[a] #Here you're making a new list with the default argument and a.
    print(id(L))
    return L
>>> f(1)
140489350175624
[1]
>>> f(1)
140489349715976
[1]
>>> f(2)
140489349718536
[2]

You can see the id of L changes everytime.

But when you use the append it goes as:

>>> def f(a, L=[]):
    L.append(a) #Here you're just appending and NOT making a new list.
    print(id(L))
    return L
>>> f(1)
140489350175624
[1]
>>> f(12)
140489350175624
[1, 12]
>>> f(3)
140489350175624
[1, 12, 3]
>>> 

Read this.

Upvotes: 1

heemayl
heemayl

Reputation: 42007

In

L.append(a)

you are appending to the same list object in all function calls, as lists are mutable.

whereas in:

L = L+[a]

you're actually rebinding the name L to the concatenation of L and [a]. Then, the name L becomes local to the function. So, in each function call L becomes different after rebinding.

Upvotes: 1

Related Questions