5

Recently, I went to a job interview for a Python developer position. The following code was one of the questions. I just had to write the output.

def extendList(val,list=[]):
    list.append(val)
    return list

list1 = extendList(10)
list2 = extendList(123,[])
list3 = extendList('a')

print "list1 = %s " %list1
print "list2 = %s " %list2
print "list2 = %s " %list3

The output is:

list1 = [10, 'a'] 
list2 = [123] 
list2 = [10, 'a']

I'm trying to understand why the first list, list1, has the 'a' value.

EDIT

I checked all the links and found out its a python "gotcha" for begginers, but want to thank the answers, can´t choose both so i´m going with the first one.

NachoMiguel
  • 983
  • 2
  • 15
  • 29
  • 1
    [This canonical answer](http://stackoverflow.com/questions/1132941/least-astonishment-in-python-the-mutable-default-argument) should help – Adam Smith Jan 26 '15 at 21:46
  • I would say it is a dupe, because this question or any answers are not likely to benefit future users. It is a known Python "gotcha!" and future readers should be redirected to the existing explanation. – Paulo Scardine Jan 26 '15 at 21:49
  • 2
    @AdamSmith it is a duplicate because the answer is basically `the default argument is mutable`. It does not have to be the exact same question. There is nothing that can be added here that is a/ not in the other question and b/ reusable by someone else. – njzk2 Jan 26 '15 at 21:49

2 Answers2

2

list1 has 'a' because the list created with extendlist('a') is appending to the same list as extendList(10)

This is no doubt the result of particulars in the way Python deals with default arguments and it's state model. You could even argue this is a bug, because it violates the closure property (if Python's methods are supposed to be closures).

For example the equivalent code in Ruby:

def extendList(val, list=[])
  list << val
  return list
end

returns

extendList(10)
# => [10]

extendList(123, [])
# => [123]

extendList('a') 
# => ['a']

This is the case in Ruby because Ruby methods are closures, that is, each method invocation carries around it's own local environment.

  • 2
    . . .and the `print` doesn't happen until after all 3 `extendList`s have been evaluated. – WAF Jan 26 '15 at 21:50
1

Actually, this isn't that basic, it's a bit of a python pitfall: Mutable Default Parameter

Compare with printing after each function call:

>>> def extendList(val,list=[]):
...     list.append(val)
...     return list
...
>>> list1 = extendList(10)
>>> print "list1 = %s " %list1
list1 = [10]
>>> list2 = extendList(123,[])
>>> print "list2 = %s " %list2
list2 = [123]
>>> list3 = extendList('a')
>>> print "list2 = %s " %list3
list2 = [10, 'a']

Also:

>>> list1 is list2
False
>>> list1 is list3
True
MattH
  • 37,273
  • 11
  • 82
  • 84