1

Consider the following sample code

class Node:
    def __init__(self, value = None, next = None):
        self.value = value
        self.next  = next

    def __str__(self):
        return str(self.value)

node1 = Node(1)
node2 = Node(2)
node3 = Node(3)

node5 = node1

node1.next = node2
node2.next = node3

#node5 = node1

def printList(node):
    while node:
        print(node)
        node = node.next

printList(node1)
printList(node5)

(example comes from https://blog.csdn.net/qq_39422642/article/details/78988976) I put node5 = node1 prior to give node1.next. However, in printList(node5), it gives the same result as printList(node1). Why node5 keeps the structure of linked list even the value is given prior to establish a linked list?

If I use normal variables

a = 3
b = a
a = 2
print(a,b)

the result is 2,3. b=a will not be affected by the code after itself, to the contrary of the linked list example in the first block. Thank you!

  • Does this answer your question? [Why variable = object doesn't work like variable = number](https://stackoverflow.com/questions/29926485/why-variable-object-doesnt-work-like-variable-number) – dspencer Apr 08 '20 at 03:26
  • Partially. I need further confirmation(s)/explanation(s). In python, does entry including a 'dot' in class, e.g., ```node5 = node1 ``` mean, two entries node5 and node1 refer to the same address in memory, then giving value to node1 or node5 means giving the value to that address in memory, hence whenever load node1 or node5 in future, they will have the same value? – user2068123 Apr 08 '20 at 04:19
  • On the other hand, if the variable does not contain a 'dot' (immutable?), e.g., a=3, b=a in the second block, means let variables locate to values in memory, in this example, 3, but not to locate at a specific address in memory, hence, later, a=2, b is still located to 3. Sorry, maybe I did not explain myself clearly. I mean like a pointer, has address and memory. – user2068123 Apr 08 '20 at 04:19

1 Answers1

1

Because in Python, variables stores the references (not Values). The statement node5 = node1 actually makes node5 to point to an object. node1 is also pointing to the same object. If you make changes to that object using either node1 or node5 and print the results using either node1 or node5, it will print the same result.

The different behavior that you have been observing using int is because int is immutable in Python. If you change the object's value, python creates a different object, stores the new value in it and updates the b to point to that object (b = a). After this statement, a will be still pointing to the old object having value 2. If you try your second code with any of the immutable in Python, you will get the same result.

If you want to copy node1 to node5, use deepcopy:

import copy

class Node:
    def __init__(self, value = None, next = None):
        self.value = value
        self.next  = next

    def __str__(self):
        return str(self.value)

node1 = Node(1)
node2 = Node(2)
node3 = Node(3)

node4 = node1
node5 = copy.deepcopy(node1)

node1.next = node2
node2.next = node3


def printList(node):
    while node:
        print(node, end=" ")
        node = node.next
    print("")

print("Node1 Id", id(node1), end=" ")
printList(node1)
print("Node4 Id", id(node4), end=" ")
printList(node4)
print("Node5 Id", id(node5), end=" ")
printList(node5)

Outputs:

Node1 Id 140465951784072 1 2 3
Node4 Id 140465951784072 1 2 3
Node5 Id 140465951810560 1

EDITED:

Added id() in my answer as suggested by @user3159253. You can see that id() returned by node1 and node4 are same. That means, they indeed point to the same object and any change made using any one of the variable (node4 or node1), it will change the same single object and hence, you will get the same result if you print using either node1 or node4.

However, if you try your second code with id():

a = 2
b = a

print("Id of a", id(a), "Value of a", a)
print("Id of b", id(b), "Value of b", b)

a = 5

print("Id of a", id(a), "Value of a", a)
print("Id of b", id(b), "Value of b", b)

Output:

Id of a 10914528 Value of a 2
Id of b 10914528 Value of b 2
Id of a 10914624 Value of a 5
Id of b 10914528 Value of b 2

As you can see after the assignment b = a, a and b were pointing to the same object but once you reassigned a's value to 5, python created the different object (and hence, id() returned different value) and changed a to point to that object having value 5. It did so because int are immutable in Python.

abhiarora
  • 9,743
  • 5
  • 32
  • 57