I tried to create a simple single-linked list as the following:
class node:
def __init__(self, data=None):
self.data = data
self.next = None
class linkedlist:
def __init__(self):
self.head = node()
def append(self, data):
curr = self.head
new_node = node(data)
while curr.next != None:
curr = curr.next
curr.next = new_node
def total(self):
curr = self.head
total = 0
while curr.next != None:
curr = curr.next
total += 1
return total
def display(self):
# added total here as well
curr = self.head
em = []
total = 0
while curr.next != None:
curr = curr.next
em.append(curr.data)
total += 1
print(f"LinkedList: {em} \n Total: {self.total()} ")
def look(self, index):
if index >= self.total():
print("ERROR: Index error" )
curr_index = self.head
idx = 0
while True:
curr_index = curr_index.next
if idx == index:
print(curr_index.data)
idx += 1
Whenever I am calling the look()
function, I am getting the following error:
curr_index = curr_index.next
^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'next'
What could this mean?
As far as I know, the curr_index
is using the self.head
, which is inturn using node()
. The node()
have does have the next
attribute.
This error isn't there when I call the other functions in the class. Moreover, the other functions -- except the look()
function -- returns their respective values error-free.
Where is my code going wrong?
In this implementation, each node point to the next node of the list, and the last one points to None
, signifying that's the end of the list.
The loop in look
tries to iterate over the nodes until it gets to the index
th item and then prints it, but the loop is not terminated there. In fact, it will continue indefinitely until at some point it passes the last element, making the current item None
, and then fail with this error.
One approach is to explicitly terminate the loop once you've reached the desired element:
def look(self, index):
if index >= self.total():
# Need to throw here, not just print
# because printing out an error won't prevent the function from moving on
throw ValueError("ERROR: Index error")
curr_index = self.head
idx = 0
while True:
curr_index = curr_index.next
if idx == index:
print(curr_index.data)
return # We're done here, return
idx += 1
Having said that, checking idx == index
on each iteration is superfolous. You could just advance curr_index
index
times explicitly:
def look(self, index):
if index >= self.total():
# Need to throw here, not just print
# because printing out an error won't prevent the function from moving on
throw ValueError("ERROR: Index error")
curr_index = self.head
for _ in range(index):
curr_index = curr_index.next
print(curr_index.data)