Reputation: 23
Can someone tell me why, after I run the code below, these are the values the variables refer to now:
x = [1, 2, 3, 5]
x1 = [1, 2, 3, 5]
x2 = [1, 2, 3]
y = [1, 2, 3]
y1 = [1, 2, 3]
y2 = [1, 2, 3]
Why isn't y = [1, 2, 3, 5]
?
And why isn't x1 = [1, 2, 3]
?
Because, following this logic:
a = 1
b = a
a = 3
b is still equal to 1, not 3.
Code is below. Thanks for your help.
def my_function(x, y):
x.append(5)
y = y + [5]
x = [1, 2, 3]
x1 = x
x2 = x[:]
y = [1, 2, 3]
y1 = y
y2 = y[:]
my_function(x, y)
Upvotes: 2
Views: 96
Reputation: 213261
The statement:
x1 = x
creates a copy of reference to the same list as pointed to by x
. Now you are passing x
to the function, where you append a value to x
:
x.append(5)
this will affect the list pointed to by the original x
outside the function, and eventually also reflect the modification for x1
. Hence x1
is [1, 2, 3, 5]
.
Now, in case of y1
, the only difference is this line in the function:
y = y + [5]
this line doesn't changes the original list referenced by y
outside the function. It creates a local variable y
, and initializes it to [1, 2, 3, 5]
. But it doesn't changes the the original list referenced by y
outside the function, and hence does not changes the list for y1
. So, y1
and y
are still [1, 2, 3]
.
You can verify it by checking the id
of both the list inside the function, and the one outside:
>>> def my_function(x, y):
... x.append(5)
... y = y + [5]
... return x, y
...
>>>
>>> x = [1, 2, 3]
>>> x1 = x
>>> y = [1, 2, 3]
>>> y1 = y
>>>
>>> x2, y2 = my_function(x, y)
>>>
>>> id(x2) == id(x)
True
>>> id(y2) == id(y)
False
So, it's clear that id
of original x
is same as the one returned from the function. But the id
of original y
is not the same as returned y
.
Upvotes: 5
Reputation: 565
You're actually dealing with a question of scope here. At first it looks like you're having aliasing issues, but your redefinition of the variables passed in only lasts within the function. Once the function is done running, the arguments passed in (to put it simply) go back to their original values. It is only within the function that they continue to have the values you reassign them to. Try printing the odd outputs before the end of the function.
Upvotes: -1
Reputation: 578
You didn't actually change the reference of y you just set it to a different reference. This wouldn't actually change the y you passed in. Just the y in the local scope of my_function.
Step through it here
Upvotes: 0
Reputation: 17532
Simple. Mutable objects (such as lists) pass by reference, whereas immutable (such as integers) pass by value.
When you do x1 = x
, x1
refers to x
; so any change to x
also applies to x1
, because they refer to the same object. x.append(5)
changes the original x
, and thus x1
by reference.
However, when you do x2 = x[:]
, you are copying the contents of the list by slicing it. Thus, you are making a new list.
When you do y = y + [5]
, you are creating a new list in the function's scope. Thus, the global y
(and y1
by reference) remains unchanged. y2
is just a copy of the original y
, so the function does not affect it at all, either.
Upvotes: 0