4

When one uses a multiple assignment in Python, such as

a, b, c = b, c, a

I've always thought that the relative order of the arguments is irrelevant (as long as one is consistent on both sides), i.e., the result would be the same if one does

c, a, b = a, b, c

While this appears to be true when a, b, c are independent variables, it seems that it may not be true when they are related.

For instance, if we define a node of a linked list as follows:

class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None

and write a function to reverse a linked list in-place:

def reverseList(head):
    """
    :type head: ListNode
    :rtype: ListNode
    """
    if head is None:
        return head
    slow = None
    fast = head
    while fast is not None:
        fast.next, slow, fast = slow, fast, fast.next

    return slow

then this works fine, for instance:

head = ListNode(1)
head.next = ListNode(2)
reverseList(head)

However, if we replace the line in the loop with a different assignment ordering:

fast, fast.next, slow = fast.next, slow, fast  

then we get an error

AttributeError: 'NoneType' object has no attribute 'next'

In the second (last) iteration, both fast and slow are not None and fast.next is None, but I still don't understand why this causes an error? Shouldn't the multiple assignments be done in parallel?

More generally, when and when not could one change the order of a multiple assignment statement without affecting the result?

Edit: I've read this question, and while it is related I still don't get how the answers there help to explain my issue. I would appreciate any elaboration on my case.

p-value
  • 608
  • 8
  • 22
  • 1
    Please note that your `a b c` examples are *not* equivalent. – Prune Aug 27 '18 at 21:22
  • @wim I've read the marked question, and while it is related I still don't get how the answers there help to explain my issue. I would appreciate any elaboration on my case. – p-value Aug 27 '18 at 21:24
  • @Prune Sorry, thanks for catching the typo! I've fixed the question. – p-value Aug 27 '18 at 21:24
  • 1
    The order of evaluation in an assignment statement is well-defined, is **not** done in parallel, and the rules are clearly described in the linked answer. Could you explain what questions remain that are not already answered? – wim Aug 27 '18 at 21:29
  • 2
    @p-value: the specific reference is where you're *mutating* one of the arguments during the assignment phase; read that part again and see how it applies to your example. That's where you run into trouble in your linked list: you mutate `fast` before you alter the *old* `fast.next`. – Prune Aug 27 '18 at 21:30
  • @Prune Thanks; after reading the docs I think that makes sense now. To summarize, the evaluation is always from left to right, but the right-hand-side is always evaluated first, which still makes the multiple assignment different than sequential assignments. – p-value Aug 27 '18 at 21:49
  • 1
    also check `dis.dis` for more fun and excitement! – Wayne Werner Aug 27 '18 at 21:57

0 Answers0