1

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...

hidefromkgb
  • 5,834
  • 1
  • 13
  • 44
Ernie Mur
  • 481
  • 3
  • 18
  • Also see https://stackoverflow.com/questions/2612802/how-to-clone-or-copy-a-list – jonrsharpe Apr 13 '19 at 16:09
  • It's not clear, to me at least, what new question you're asking after your edits (if any). If you have a further question, it might be better opening a completely new question. – Zorawar Apr 13 '19 at 20:45
  • @Zorawar: I just wanted to complete my question with the conclusion which I have drawn from the solution link, because the link consists of several longer messages. – Ernie Mur Apr 25 '19 at 13:50
  • @ErnieMur: Ah, I see. There was a reopen request, and I thought I'd leave some feedback just in case there _was_ something else being asked. OK. – Zorawar Apr 25 '19 at 15:19

1 Answers1

0

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.

DjaouadNM
  • 22,013
  • 4
  • 33
  • 55
  • Here, I wanted to modify the list. The problem is, that I did not know that the default parameter is evaluated only once at program start and the result stays static in the function. – Ernie Mur Apr 13 '19 at 17:27