-1

Before asking, I read the accepted answer to the question "How do I pass a variable by reference?" and documentation linked in that same answer: "How do I write a function with output parameters (call by reference)?"

I have a related question: Does Python automatically synchronize a variable whose value is a reference to another object? In other words, if I assign an object as the value of a variable, is the variable updated whenever the object is modified?

I have a specific problem where it appears that Python updates the value of a variable with an object as its value without any code explicitly triggering an update. I created a function that was supposed to be part of a solution to the ROT13 (rotate right 13 times) problem: shift an array to the right 13 times. Here is the function's code:

array = [0, 1, 2, 3, 4, 5]
print(array)
backup = array

#backup = [n for n in array]

for i in range( 1, (len(backup)) ):
    array[i] = backup[i - 1]

array[0] = backup[-1]
backup = array
print(array)

The output of that code is wrong: [0, 0, 0, 0, 0, 0] . However, when I replace line 3 (backup = array) with backup = [n for n in array], the answer is correct: [5, 0, 1, 2, 3, 4]

I inferred that whenever the for-loop executed, the value of backup was updated because its value is inherently a reference to the object array. It appears to me that when array[1] was assigned the value zero, backup[1] was also assigned zero instead of holding the value 1. Because of that, the for-loop simply assigned the value zero to every other variable in backup thru array.

If I instead assigned backup to a list object distinct from array using backup = [n for n in array], modifying array would not modify backup.

What is the actual cause of this behavior?

Union find
  • 7,759
  • 13
  • 60
  • 111
Joachim Rives
  • 471
  • 6
  • 19

2 Answers2

2

In your example backup and array are both references to the same object. That is clear with this code example:

>>> array=[1,2,3,4]
>>> backup=array
>>> id(array)
4492535840
>>> id(backup)
4492535840

So your code is equivalent to this:

array = [0, 1, 2, 3, 4, 5]
print(array)

for i in range( 1, (len(array)) ):
    array[i] = array[i - 1]

array[0] = array[-1]
print(array)

Does that help?

vy32
  • 28,461
  • 37
  • 122
  • 246
  • Yes, it does. Does this mean that (a) variables are references to objects and that (b) assigning a variable to another variable makes them references to the same object? – Joachim Rives Dec 12 '19 at 03:12
  • @JoachimRives Variable are not assigned to each other. Rather, a variable is assigned the *result of evaluating an expression*. So yes; both variables will end up *referring to* (aka *naming* or even *referencing*) the same object. (Some languages make copies-on-assignment; Python does not! No copy/clone/duplicate of objects occurs implicitly.) – user2864740 Dec 12 '19 at 03:21
1

There’s no synchronization going on. Instead, there’s only one list. Both variables reference that same list – you can think of the variables as pointing to it or as tagging it, if that helps. You perform operations on values and not on variables, so given that there’s only one list, all of the operations change it and read changes back from the same one.

Ry-
  • 218,210
  • 55
  • 464
  • 476
  • "Both variables *name* the same list"; like people, objects can have multiple *names* that refer to the same entity. (eg. Samuel Langhorne Clemens and Mark Twain.) – user2864740 Dec 12 '19 at 03:14
  • @user2864740: But people *have* names and values don’t *have* variables. No analogy is perfect. – Ry- Dec 12 '19 at 03:16
  • @user2864740: Doesn’t change the relationship. – Ry- Dec 12 '19 at 03:16
  • It invalidates the proposition that "People *have* [as in, are inseparable from] names" any more than "Objects *have* names". A name is merely a label used to *refer to* an entity. If that entity happens to also 'contains a name', that's a separate consideration. – user2864740 Dec 12 '19 at 03:17
  • 1
    @user2864740: Anyway, I already linked to the tagging article, which is the same analogy under a different name. – Ry- Dec 12 '19 at 03:19