Reputation: 267
def f(x, y):
x.append(x.pop(0))
x.append(y[0])
return x
a = [4,5]
b = [1,2,3]
w = f(a,b) + f(a,b)
w turns out to be [4,1,5,1,4,1,5,1] However if I manually go through the code (in my head), I get [5,4,1,4,1,5,1]
Why is this?
f(a,b) = [5,4,1] right?, so then a would be = [5,4,1] and b = [1,2,3].
So then f(a,b) = [4,1,5,1] which would be: [5,4,1] + [4,1,5,1] = [5,4,1,4,1,5,1] NOT [4,1,5,1,4,1,5,1]
Why does the code change this? What am I doing wrong when trying to run through the code myself?
Upvotes: 3
Views: 260
Reputation: 25954
f(a,b) = [5,4,1] right?, so then a would be = [5,4,1] and b = [1,2,3].
All correct. However. If you look at what f
is doing, it is just returning the mutated x
(i.e. mutating a
). So do it twice:
f(a,b)
Out[40]: [5, 4, 1]
a
Out[41]: [5, 4, 1]
f(a,b)
Out[42]: [4, 1, 5, 1]
a
Out[43]: [4, 1, 5, 1]
then concatenate that with itself. That's what w
is: just a + a
, after having mutated a
twice.
Upvotes: 0
Reputation: 798686
Both calls return the same list, namely the object bound to a
, resulting in the second returned value (which is still the object bound to a
) being added to itself. The function only mutates the list, never replaces it.
Upvotes: 6
Reputation: 3582
Your problem is that your code both changes the original list and although returns a reference to it. When you invoke f for the second time (never use one-letter names !!!) you change the result of the original call as well. Let's do it by stages:
n [53]: a1 = f(a,b)
In [54]: a
Out[54]: [5, 4, 1]
In [55]: a2 = f(a,b)
In [56]: a2
Out[56]: [4, 1, 5, 1]
In [57]: a
Out[57]: [4, 1, 5, 1]
This illustrates my point (function id returns reference to an object)
In [77]: id(a)
Out[77]: 145114860
In [78]: id (f(a,b))
Out[78]: 145114860
As you may see, your function has a side effect. If you rewrite it like this
def f(x, y):
x.append(x.pop(0))
x.append(y[0])
return copy(x)
The second call will not on impact the result of the first call -
In [74]: id(a)
Out[74]: 145114860
In [75]: id (f(a,b))
Out[75]: 145113356
and the result will be [5, 4, 1, 4, 1, 5, 1]
Upvotes: 3