2

I'd like to clarify a simple pointer mechanic in Python. Consider the following:

u = [1,2]
v = [u,3]
print(v)
u[0] = 100
print(v)

Then the result is

[[1,2],3]
[[100,2],3]

Meanwhile if we perform

u = [1,2]
v = [u,3]
print(v)
u = [100,2]
print(v)

Then the result is

[[1,2],3]
[[1,2],3]

I think this happens because in the first code, the pointer that u stores doesn't change throughout while in the second code, the pointer that u stores changed from the declaration u=[100,2] but the declaration v=[u,3] stored the initial pointer itself and not the variable u.

Is this the correct explanation as to why this happened?

7
  • 2
    Definitely. To get the same behaviour for the second array you would have to do u[:] = [100, 2]. Commented Dec 28, 2019 at 18:25
  • 6
    Mandatory link to Ned Batchelder’s article: nedbatchelder.com/text/names.html Commented Dec 28, 2019 at 18:34
  • 2
    The assignment in the second example makes u point to a different object, so operations on/to u no longer affect the object in v. - nedbatchelder.com/text/names.html. … docs.python.org/3/reference/…docs.python.org/3/reference/…. Commented Dec 28, 2019 at 18:34
  • If you run both of your examples in Python Visualizer tool you will easily be able understand what's happening pythontutor.com/visualize.html#mode=edit Commented Dec 28, 2019 at 18:37
  • 1
    Python containers hold references to objects. Everything is an object. A value is an object. A name is a reference (and either term is preferable to the term variable, which recalls a box storing a value, as this does not apply to Python). You bind names to objects, or change objects in place. Re binding a name to another object does not affect the original object unless there are no more references to it. Commented Dec 28, 2019 at 18:38

1 Answer 1

4

Python has no concept of pointers and thinking about Python constructs in terms of pointers can be misleading. Python has names and references to objects instead of pointers (everything is an object in Python).

The assignment operator (=) is used to bind a name to an object with a reference. When you access the object with its name, you get the object instead of the reference. You can't access the value of the reference and there is no way to manipulate references similar to pointer arithmetic in C. With this in mind, let me break down your code in Python terms:

# A new list object is created and bound to the name `u`. 
# It only has `int` elements which are immutable
u = [1,2]
# A different list object is created and bound to the name `v`.
# Its first element is an other list object which is bound to the name `u` at this point. 
v = [u,3]
print(v)
# __setitem__(0, 100) is called on the list object under the name `u`
# The first element of `v` remains this altered object.
u[0] = 100
print(v)

# Same as before
u = [1,2]
v = [u,3]
print(v)
# A new list object is created and bound to the name `u`.
# The previous list object bound to `u` remains the first element of `v` which is unchanged.
u = [100,2]
print(v)

Hope this helps

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.