Hello all,
Problem: I have difficulties understanding why the error in the code below appears.
Edit2: I am working on improving the code.
Erroneous Code/ First Piece of Code:
def pop(self) -> str or None:
"""Removes the last item and returns it."""
if self.before_last:
removed_node = self.end.value
self.before_last.next = None
node = self.begin
count = 0
while node.next:
node_before_last = node
node = node.next
count += 1
if count == 1:
self.begin = node_before_last
self.end = node
self.before_last = None
else:
self.before_last = node_before_last
self.end = node
return removed_node
elif self.begin.next is None: # Error here
removed_node = self.begin.value
self.begin = None
return removed_node
elif self.begin.next:
removed_node = self.end.value
self.begin.next = None
return removed_node
return None
(Code is my version and is part of the SingleLinkedList Class, page 69 of LMPTHW)
Error: elif self.begin.next is None:
AttributeError: ‘NoneType’ object has no attribute 'next’
What I do not understand is: Why does the code break at this if? If self.begin = None, does it mean that self.begin.next is also None or just that self.begin does not exit, hence no attributes?
What is more weird is that the following code runs with no problems.
Second Piece of Code:
def pop(self) -> str or None:
"""Removes the last item and returns it."""
if self.before_last:
removed_node = self.end.value
self.before_last.next = None
node = self.begin
count = 0
while node.next:
node_before_last = node
node = node.next
count += 1
if count == 1:
self.begin = node_before_last
self.end = node
self.before_last = None
else:
self.before_last = node_before_last
self.end = node
return removed_node
elif self.begin.next is None:
removed_node = self.begin.value
self.begin.value = None # change introduced here: instead of self.begin, there is self.begin.value -> AttributeError no longer appears
return removed_node
elif self.begin.next:
removed_node = self.end.value
self.begin.next = None
return removed_node
return None
Why does the code run now?
Thanks!
Edit1: Added the full code.
class SingleLinkedListNode(object):
def __init__(self, value: None or int, nxt: 'object' or int = None):
self.value = value
self.next = nxt
def __repr__(self):
nval = self.next and self.next.value or None
return f"[{self.value}:{repr(nval)}]"
# The repr() method returns a printable representational string of the given object.
class SingleLinkedList(object):
def __init__(self):
self.begin = None
self.end = None
self.before_last = None
def push(self, obj: str):
"""Appends a new value at the end of the list."""
node = SingleLinkedListNode(obj, None)
if self.begin is None:
self.begin = node
elif self.begin.next is None:
self.end = node
self.begin.next = self.end
else:
self.before_last = self.end
self.end = node
self.before_last.next = self.end
def pop(self) -> str or None:
"""Removes the last item and returns it."""
if self.before_last:
removed_node = self.end.value
self.before_last.next = None
node = self.begin
count = 0
while node.next:
node_before_last = node
node = node.next
count += 1
if count == 1:
self.begin = node_before_last
self.end = node
self.before_last = None
else:
self.before_last = node_before_last
self.end = node
return removed_node
elif self.begin.next is None:
removed_node = self.begin.value
self.begin.value = None
return removed_node
elif self.begin.next:
removed_node = self.end.value
self.begin.next = None
return removed_node
return None
def shift(self, obj):
"""Another name for push."""
def unshift(self):
"""Removes the first item and returns it."""
def remove(self, obj):
"""Finds a matching item and removes it from the list."""
def first(self):
"""Returns a *reference* to the first item, does not remove."""
def last(self):
"""Returns a reference to the last item, does not remove."""
def count(self):
"""Counts the number of elements in the list."""
node = self.begin
count = 0
while node:
count += 1
node = node.next
return count
def get(self, index):
"""Get the value at index."""
def dump(self):
"""Debugging function that dumps the contents of the list."""