Suppose head
names element 0 of the list, which has a .next
referring to element 1 etc. to start.
In the first case build the tuple (head, head.next.next)
, which is to say, (element 0, element 2)
. Then we assign those values to head.next.next
and head.next
respectively, and in that order. That is to say, the head.next
(element 1 previously) has its next
altered to refer to element 0, and the head
(element 0) has its next
altered to refer to element 2. We have reversed the element 0 -> element 1 link into an element 1 -> element 0 link, and by temporarily making element 0 connect to element 2, we can repeat the process.
In the second case, we simply have the operations swapped on both sides, so it would seem like the net effect should be the same. However, this time we are tripped up by a dependency. Because the assignment to head.next
happens before the assignment to head.next.next
, the head.next.next
doesn't update the prior head.next
, but the one we just set up. That is: element 0 is connected to element 2, but then element 2 (rather than element 1) is the head.next
that gets connected to element 0. Now we have built a cycle between those two elements, and attempts to continue the procedure thus get stuck in a loop (if implemented iteratively, or in unbounded recursion as described by OP for a presumed recursive implementation).
Normal uses of this a, b = x, y
syntax in Python involve a
and b
being unrelated. Here they are related, so the order of assignment matters, despite that the syntax is normally used specifically to avoid worrying about order of assignment (for "state updates"). Linked list logic is the sort of thing where order of assignment needs to be precise, which is another good reason not to implement this stuff yourself - except, of course, as an exercise to practice detailed and precise thinking about algorithms.