Search code examples
python-3.xlinked-list

How to print linked list in python without None error


I have a simple linked list I am building and I am able to print it in reverse order (first node added is printed last) but I would like to print it in normal order. However I am not sure why I keep getting an error about not being able to print None.

class Node:
  def __init__(self, data):
    self.data = data
    self.next = None
  def addNextData(self, data):
    self.next = Node(data)
    return self.next
  def __str__(self):
    if(self is None):
      return "None"
    print(self.data)
    return print(self.next)

node = Node("a")
node.addNextData("b") \
  .addNextData("c") \
  .addNextData("d")
print(node)


Traceback (most recent call last): TypeError: __str__ returned non-string (type NoneType)

I have resorted to doing it like this but it print unnecessary blank strings/lines:

  def __str__(self):
    if(self is None):
      return "None"
    print(self.data)
    print(self.next)
    return ""

I am able to do this iteratively but maybe there is a more elegant way to do it via print/recursive:

  def __str__(self):
    head = self
    str = ''
    while(head is not None):
      str = str + head.data  + '->'
      head = head.next
    return str + 'None'
      

I am having a hard time understanding why this (reverse order printing) does not throw the None error. :

def __str__(self):
    print(self.next)
    return self.dat

Also confused since print(None) doesn't throw an error.


Solution

  • You don't want to print anything from a __str__ method - it should only return a str. print is a function that prints a string but doesn't return anything so return print(...) is equivalent to return None. This is the cause of your TypeError: __str__ returned non-string (type NoneType) error.

    if(self is None):
          return "None"
    

    Is also a no-op as self will never* be None as it is (by definition) an instance of your Node type.

    In your case you could do something like

    class Node:
      def __init__(self, data):
        self.data = data
        self.next = None
      def addNextData(self, data):
        self.next = Node(data)
        return self.next
      def __str__(self):
          value = str(self.data)
          n = self.next
          while n is not None:
              value += "->" + str(n.data)
              n = n.next
          return value
    
    node = Node("a")
    node.addNextData("b") \
      .addNextData("c") \
      .addNextData("d")
    print(node)
    

    The __str__ method could be made recursive instead with something like the following but an iterative approach is generally better than a recursive version that does the same thing.

    def __str__(self):
        if self.next is not None:
            return str(self.data) + ", " + str(self.next)
        else:
            return str(self.data)
    

    * Never unless you intentionally go out of your way to call it directly with None, eg(Node.__str__(None))