# Re: functions, list, default parameters

• From: Dave Angel <davea@xxxxxxxx>
• Date: Fri, 22 Oct 2010 07:59:11 -0400

On 2:59 PM, Sean Choi wrote:
I found two similar questions in the mailing list, but I didn't understand
the explanations.

I ran this code on Ubuntu 10.04 with Python 2.6.5.

Why do the functions g and gggg behave differently? If calls gggg(3) and
g(3) both exit their functions in the same state, why do they not enter in
the same state when I call gggg(4) and g(4)?

# ---------------------------------------------------------------------- my
code:
def gggg(a, L=[]):
print "enter function"
print "a = ", a, "and L = ", L
if L == []:
print "hey, L is empty"
L = []
L.append(a)
print "after append, L = ", L
return L

def g(a, L=[]):
print "enter function"
print "a = ", a, "and L = ", L
if L == []:
print "hey, L is empty"
L.append(a)
print "after append, L = ", L
return L

print gggg(3)
print gggg(4)
print gggg(7)
print g(3)
print g(4)
print g(7)

# ---------------------------------------------------------------------- my
output:
-------------------gggg calls
enter function
a = 3 and L = []
hey, L is empty
after append, L = [3]
[3]
enter function
a = 4 and L = []
hey, L is empty
after append, L = [4]
[4]
enter function
a = 7 and L = []
hey, L is empty
after append, L = [7]
[7]
-------------------g calls
enter function
a = 3 and L = []
hey, L is empty
after append, L = [3]
[3]
enter function
a = 4 and L = [3]
after append, L = [3, 4]
[3, 4]
enter function
a = 7 and L = [3, 4]
after append, L = [3, 4, 7]
[3, 4, 7]

You deserve a better answer than "Don't do that." That is good advice, but if I were asking, I'd want a clearer explanation of what's going on.

In the g() function, you are seeing the effect that when a mutable object is used as a default parameter, it's shared among all uses of the function. So each time you enter the function, you get the value the object had when the function was last exited.

It's important to point out that the behavior is the same for a immutable object, but since it can't be changed, nobody cares. The immutable object will have the same value it was first created with.

So the secondary question is why function gggg() seems to have different behavior. I haven't seen any responses that addressed that.

The answer is that gggg() doesn't change the original object. Every time through the function, the local attribute L is bound to a new empty list, different from the one that was the default argument. And it's the new one that's modified, and returned. The original empty object is still there, to be used the next time the function is called.

The problem many new Python programmers have is to separate the notion of the symbol L and the object. L is *not* a container for the list object, it is simply bound to it. And the empty list object lives on even when you bind L to a different one.

Perhaps it'd help to print id(L) before and after the assignment, in function gggg(). After the assignment, L is bound to a new object, with a different id. That new object is appended to, returned, and printed. Then it's thrown away. Next time through the function, the original object is used for default argument.

If you needed to empty a list in-place, without changing to a new object, you could use
L[:] = []

DaveA

.