1

I'm trying to understand some code that reverses a linked list.

Here's how I'm constructing a linked list:

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

def initialize():
     start = Node(0)
     prev = start
     for i in range(1, 6):
          cur = Node(i)
          prev.next = cur
          prev = cur
     return start

Here's the correct code in the answer:

def reverse_list(head):
     new_head = None
     while head:
          head.next, head, new_head = new_head, head.next, head 
     return new_head

And here's what I have:

def reverse_list(head):
     new_head = None
     while head:
          new_head, head, head.next = head, head.next, new_head 
     return new_head

However, my code throws an AttributeError when reversing a linked list:

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

I'm using the exactly same replacements as the correct answer, only in a different order. Why does my code throw an error? Does order matter when it comes to one line variable reassignments?

Daniel Q
  • 117
  • 2
  • 11

1 Answers1

1

The problem is that head.next becomes None after the first iteration. Then on the second iteration head gets assigned to head.next i.e. is set to None before calling head.next (on the left side) hence the error. For instance let's have the following scenario:

class Spam:

def __init__(self):
    self.foo = 1
    self.bar = 2


spam = Spam()
spam.foo, spam.bar = spam.bar, spam.foo
print(spam.foo, spam.bar) # 2, 1 as expected

but when we do:

spam.foo, spam, spam.bar = spam.bar, None, spam.foo

results in:

Traceback (most recent call last): File "main.py", line 9, in spam.foo, spam, spam.bar = spam.bar, None, spam.foo AttributeError: 'NoneType' object has no attribute 'bar'

So to answer your question the order does matter. In fact changing the order of the toy example to:

spam.foo, spam.bar, spam = spam.bar, spam.foo, None

does not throw any exceptions.

Dani Mesejo
  • 55,057
  • 6
  • 42
  • 65
  • Does Python assign variables like this from left to right, then? I understand this issue, but I still don't understand why the "correct" response (which seems like it should set head.next to None as well) works. – Daniel Q Oct 24 '18 at 04:00
  • I would assume so. In the other answer `head.next` gets call before changing the value of `head` therefore is not set to `None` before the calling. – Dani Mesejo Oct 24 '18 at 04:06
  • @DanielQ Updated the answer! – Dani Mesejo Oct 24 '18 at 04:12