As a C++ programmer I got unexpected behaviour in Python. In the example below, the output is:

y:A1
A1
B1

I however would have expected this output:

B1

I used python 2.7. For me it is surprising that in the second call of the function the default parameter has already the value from the result of the previous call. Should it not be an empty list?

Here is the python code:

def f( x, y=[]):
    for z in y:
        print "y:" + str(z)
    result = y   
    result.append(x+'1')
    return result

l = f('A') 
l = f('B')

for x in l:
    print x 

Edit: As indicated by others, this question is a duplicate. The the short answer is that python evaluates default parameters only once at program start and stores the result statically in the function. From C++ I would have expected that it is evaluated every time the function is called and stored only locally and not static.

In my code I see two dangerous situations with this behaviour: A) the function should modify a list but it should start with an empty list if the parameter is not passed at function call. Now I had the problem that the list grew more and more.

The solution would be a) remove the default value of the parameter in order I am forced to provide an empty list at least:

def f( x, y):
    result = y
    result.append(x+'1')
    return result

l = f('A',[]) 
l = f('B',[])

b) Use None as default parameter:

def f( x, y=None):
    result = y or []
    result.append(x+'1')
    return result

B) The other problem is that the default parameter is calculated at program start and I used a timestamp of now as default parameter...

1 Answers

0
Mr Geek On

result = y makes the names result and y point to the same object in memory, so the list y in the second call will not be empty (because now any modification to result will also appear in y (in your case you're appending to it)), try this (list slicing) and it will give you your desired output:

result = y[:] # elements of y, from the first to the last

This slicing is equivalent to result = y in the values, but result and y will point to two different objects in memory, because slicing creates a new list.