Home > Blockchain >  Why are the results different depending on how to assign?
Why are the results different depending on how to assign?

Time:10-24

When I tried to reverse the Linked list, I noticed that the results varied depending on how I did the assignments.

Why does it happen as bellow?

class ListNode:
    def __init__(self, val=0, next: Optional["ListNode"] = None):
        self.val = val
        self.next = next


# It works as expected with unpacking assignment.
nodes = ListNode(1, ListNode(2, ListNode(3, ListNode(4, ListNode(5)))))
rev = None
while nodes is not None:
    rev, rev.next, nodes = nodes, rev, nodes.next
# rev = [5, 4, 3, 2, 1]

# But dose not work as expected when assigning one by one.
cnt = 0
nodes = ListNode(1, ListNode(2, ListNode(3, ListNode(4, ListNode(5)))))
rev = None
while nodes is not None:
    if cnt > 10:
        break
    rev = nodes
    rev.next = rev
    nodes = nodes.next
    cnt  = 1
# rev = [1, 1, 1, 1, 1...] Infinite loop in circular reference!

My Environments:

  • Python 3.10.7

Thanks a lots.

CodePudding user response:

What applies here is

rev, rev.next, nodes = nodes, rev, nodes.next

the right-hand expression is evaluated before the left-hand assignement. So you assign nodes.next to nodes and rev to rev.next. That's why it is correct.

In the second loop. You killing the link here

rev.next = rev

after this it can not stop

CodePudding user response:

The first example is a tuple assignment. They all happen at the same time.

In the second example the assignments happen one after the other and rev.next points to itself which causes the self-reference loop.

Consider the below example:

class F: pass

a = F()
b = F()
c = F()

a.name = 'a'
b.name = 'b'
c.name = 'c'

a.name, b.name, c.name = c.name, b.name, a.name

print(a.name)
print(b.name)
print(c.name)

outputs

c
b
a

but

class F: pass

a = F()
b = F()
c = F()

a.name = 'a'
b.name = 'b'
c.name = 'c'

a.name = c.name
b.name = b.name
c.name = a.name

print(a.name)
print(b.name)
print(c.name)

outputs

c
b
c

This is due to the fact that by the time c.name = a.name is executed, a.name is already 'c' and not 'a'.

  • Related