Ghozt
Ghozt

Reputation: 267

why does this .pop(0) work like this

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

Answers (3)

roippi
roippi

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

Ignacio Vazquez-Abrams
Ignacio Vazquez-Abrams

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

volcano
volcano

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

Related Questions