Reputation:
Following example:
a = 1
b = a
b = 3
print(a) # gives 1
But, when I do:
a = [1,2]
b = a
b[0] = 3
print(a) # gives [3,2]
How do I know whether a variable is treated like a (C++ type) reference or a plain variable? Are elementary data types just an exception to the 'everything is a reference' rule? What detail of the underlying mechanics am I missing?
Upvotes: 3
Views: 1246
Reputation: 13723
For a better grasp of this kind of issues, I would encourage you to use the Online Python Tutor. This is an extremely handy tool that renders a graphical representation of the objects in memory while the code is executed step by step.
To show the Online Python Tutor in action I have splitted a toy example into small snippets and then captured the corresponding screenshots. Hopefully this will help you figure out how Python referencing works.
a = 1
b = a
b = 2
x = [a, b]
y = x
y[1] = 3
If you want to play around with this code, follow this link.
Upvotes: 1
Reputation: 308121
All variables in Python are references. Elementary data types aren't an exception.
In the first example, you reassign b
. It no longer references the same object as a
.
In the second example, you modify b
. Since you've previously set a
and b
to be references to the same object, the modification applies to a
as well.
Upvotes: 3
Reputation: 25813
Everything is a reference. All python variables reference objects, all objects can have more than one reference.
The difference you're seeing is between the assignment operator and the __setitem__
operator. The syntax is similar, but they do different things.
This is an assignment, it updates the reference of variable var
.
var = 'something'
This uses setitem, it's essentially a method call on the left hand side object.
obj[i] = 'thing'
# is the same as
obj.__setitem__(i, 'thing')
What __setitem__
does depends on the type, but generally it will modify obj
. In that sense, b[0] = 3
is more b.append(3)
than it is like b = 3
. Immutable types do not have a setitem method and throw an error on the setitem operator.
Upvotes: 0
Reputation: 44344
Every name is a plain reference.
A variable name is a reference to an object, and what matters is the properties of the object. Rule: numbers (int, float, etc.), strings, tuples (and others) are immutable - read-only. Lists, dictionaries, sets (and others) are mutable.
So the difference you observed is because int's are immutable - they cannot be changed. Whereas lists are mutable - they can be changed.
Assigning a = b
in both cases copies the reference. It's what happens when you reassign b
, in this case a new object is created referenced by the left-hand-side. With a mutable object the object referenced is changed, and it would not matter which reference is used.
Upvotes: 0