3

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.

13
  • 1
    adding 2 list creates a new list, but append adds element to an existing list. Try L += [a] Commented Mar 11, 2018 at 8:45
  • 1
    its bad practice to use List,Dict as default values in Python, see docs.quantifiedcode.com/python-anti-patterns/correctness/… Commented Mar 11, 2018 at 8:46
  • 1
    Do not assign to default value mutable objects. Commented Mar 11, 2018 at 8:47
  • 1
    @UmangGupta because you never mutate L - it always remains an empty list. L = L+[a] just makes the name L bind to the result of what's effectively [] + [a] which is a new list.... The original L is never affected. Commented Mar 11, 2018 at 8:52
  • 1
    @UmangGupta you might find nedbatchelder.com/text/names.html a useful read... Commented Mar 11, 2018 at 8:54

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.