Reputation:
In defining variable of a list object, for example:
x = [1,2,0.2,3,4]
y = x
x.sort()
I would expect that y
is still equal to [1, 2, 0.2, 3, 4]
, but it does not. The value of y
changed as x
changed. To counter this, I found that using y = x.copy()
can preserve the value in the first line.
On the other hand, another example :
x = 5
y = x
x = 4
from this the value of y
is still 5
, it does not change as x
change.
My question : is this due to the design in list's class, or there is another explanation? I found the dynamic change also happen when using x.append(value)
. Any insight is appreciated. Regards, Arief
Upvotes: 0
Views: 237
Reputation: 289
There is no need to draw graphs manually to understand what data is shared between variables, you can generate accurate graphs at run-time using memory_graph:
import memory_graph as mg
mg.config.no_reference_types.pop(int, None) # show references to ints
mg.config.no_reference_types.pop(float, None) # show references to floats
x = [1, 2, 0.2, 3, 4]
y = x
x.sort()
mg.show(locals()) # show graph
The resulting graph shows x
and y
share their data:
Because 'int' and 'float' are immutable types there is no need draw references to them in your mental model, so memory_graph doesn't do that by default resulting in more readable graphs:
import memory_graph as mg
x = [1, 2, 0.2, 3, 4]
y = x
x.sort()
mg.show(locals()) # show graph
If you make a shallow copy of x instead, the graph looks like this and y
is unaffected by sorting x
:
import memory_graph as mg
x = [1, 2, 0.2, 3, 4]
y = x.copy() # make a shallow copy of x
x.sort()
mg.show(locals()) # show graph
Making a copy is not necessary for integers because an 'int' is an immutable type and a value of an immutable type gets copied automatically when it is modified. See this explanation of the Python Data Model for more information.
Full disclosure: I am the developer of memory_graph.
Upvotes: 0
Reputation: 152657
Every variable is just a pointer to an Python object, if you have two variables pointing to the same object then you'll see the changes in each of them (and .sort
works in-place, if you want a new list
you should use x = sorted(x)
). However if you re-assign a variable then it will point to a different object.
I included some images to better visualize what's happening (not high-quality but I hope it conveys the message).
x = [1,2,0.2,3,4]
y = x
If you copy
(it's a shallow copy so the list-contents still refer to the same items!):
x = [1,2,0.2,3,4]
y = x.copy()
Your second case is just the same:
x = 5
y = x
But then you re-assign the variable x
(so it points to another object thereafter):
x = 4
Upvotes: 2
Reputation: 403
The problem is, y
and x
are just references to the class list.
When you do something like:
y=x
You are coping the reference of the class and not creating another one.
When using copy
you are doing a shallow copy that are creating a new class, copying all elements again to this new object.
Python manual presents a explanation and others operators used to actually copy a full class.
Upvotes: 0