'NoneType' object has no attribute 'value' - python

when deleting the entire linked list using the "delete_entire(self)" method. It throws no attribute error. Although the above code is running fine. Instead of printing the blank list, it is giving the no attribute error.
class Node:
def __init__(self,value):
self.value = value
self.next = None
class CircularSinglyLinkedList:
def __init__(self):
self.head = None
self.tail = None
def __iter__(self):
node = self.head
while True:
yield node
if node.next is self.head:
break
node = node.next
def insertion(self, value, location):
new_node = Node(value)
if self.head is None:
self.head = new_node
self.tail = new_node
self.tail.next = self.head
else:
if location == 0:
new_node.next = self.head
self.head = new_node
self.tail.next = new_node
elif location == -1:
self.tail.next = new_node
new_node.next = self.head
self.tail = new_node
else:
temp_node = self.head
index = 0
while index < location -1:
if temp_node.next is self.head:
break
temp_node = temp_node.next
index += 1
next_node = temp_node.next
temp_node.next = new_node
new_node.next = next_node
if new_node.next is self.head:
self.tail = new_node
#---------------------------------------------------------------------------------------------#
# deleting the entire linked list
def delete_entire(self):
self.head = None
self.tail.next = None
self.tail = None
cll = CircularSinglyLinkedList()
cll.insertion(2,1)
cll.insertion(3,2)
cll.insertion(5,3)
cll.insertion(6,4)
cll.insertion(0,0)
cll.insertion(10,-1)
print([node.value for node in call])
output = [0, 2, 3, 5, 6, 10]
cll.delete_entire()
print([node.value for node in call])
AttributeError: 'NoneType' object has no attribute 'value'
The expected output is to be
[ ]

Your __iter__() method always yields once, even when the list is empty, since it does yield node before checking whether node is None. Whenthe list is empty, that will yield None, and the caller will try to use None.value.
You should stop the loop as soon as node is None.
def __iter__(self):
node = self.head
while node:
yield node
node = node.next

Related

Unable to Insert node in Circular Singly linked list

I'm not able to get the desired output in the given code. The code is about inserting nodes in the circular singly linked list. Please correct this code as per the problems stated.
class Node:
def __init__(self,value):
self.value = value
self.next = None
class CircularSLL:
def __init__(self):
self.head = None
self.tail = None
def __iter__(self):
node = self.head
while node:
yield node
if node.next == self.head:
print('break')
break
node = node.next
def insertnode(self, value, location):
new_node = Node(value)
# check if head is None or not
if self.head is None:
self.head = new_node
self.tail = new_node
new_node.next = self.head
else:
# At the start
if location == 0:
new_node.next = self.head
self.head = new_node
self.tail.next = self.head
# At the end
elif location == -1:
new_node.next = self.tail.next
self.tail.next = new_node
self.tail = new_node
else:
# At specific location
temp_node = self.head
index = 0
while index < location - 1:
# node is the last element
if temp_node.next == self.head:
break
temp_node = temp_node.next
index += 1
next_node = temp_node.next
temp_node.next = new_node
new_node.next = next_node
if temp_node.next == self.head:
self.tail == temp_node
self.tail.next = self.head
return 'The node has been successfully inserted'
cll = CircularSLL()
cll.insertnode(1,0)
cll.insertnode(3, 1)
cll.insertnode(4, 2)
cll.insertnode(5, 3)
cll.insertnode(6, 4)
print([node.value for node in call])
output = [1,3,4,5,6 ]
1st problem - when inserting at index = '0'.
cll.insertnode(10,0)
output = [10,1]
expected
output = [10,1,3,4,5,6]
2nd problem - when putting location = '-1'
cll.insertnode(30, -1)
output = [1, 30]
expected
output = [10,1,3,4,5,6,30]
With your test setup, tail is never getting set after the first node is inserted.
(Pdb) [c.value for c in cll]
[1, 3, 4, 5, 6]
(Pdb) cll.head.value
1
(Pdb) cll.tail.value
1
(Pdb) cll.head is cll.tail
True
Your first problem is you have self.tail == temp_node instead of self.tail = temp_node, so let's fix that. Still, we're not getting the expected output:
[1, 3, 4, 5, 6]
The next problem is that by the time you check if temp_node.next is self.head:, you have already set temp_node.next to be new_node. It will never be self.head. I believe you intended to check new_node.next at this point, as it is now the last element.
Simply replace
if temp_node.next == self.head:
self.tail == temp_node
self.tail.next = self.head
with
if new_node.next is self.head:
self.tail = new_node
to get
class Node:
def __init__(self,value):
self.value = value
self.next = None
class CircularSLL:
def __init__(self):
self.head = None
self.tail = None
def __iter__(self):
node = self.head
while node:
yield node
if node.next is self.head:
break
node = node.next
def insertnode(self, value, location):
new_node = Node(value)
# check if head is None or not
if self.head is None:
self.head = new_node
self.tail = new_node
new_node.next = self.head
else:
# At the start
if location == 0:
new_node.next = self.head
self.head = new_node
self.tail.next = self.head
# At the end
elif location == -1:
new_node.next = self.tail.next
self.tail.next = new_node
self.tail = new_node
else:
# At specific location
temp_node = self.head
index = 0
while index < location - 1:
# node is the last element
if temp_node.next is self.head:
break
temp_node = temp_node.next
index += 1
next_node = temp_node.next
new_node.next = next_node
temp_node.next = new_node
if new_node.next is self.head:
self.tail = new_node
return 'The node has been successfully inserted'
cll = CircularSLL()
cll.insertnode(1,0)
cll.insertnode(3, 1)
cll.insertnode(4, 2)
cll.insertnode(5, 3)
cll.insertnode(6, 4)
cll.insertnode(10,0)
cll.insertnode(30, -1)
print([node.value for node in cll])
Output:
[10, 1, 3, 4, 5, 6, 30]
I have also replaced == with is in several places to more clearly test for identity rather than equivalent values.

AttributeError: 'NoneType' object has no attribute 'next' and Function missing 2 required positional arguments: 'x' and 'y'

I am trying to write a program to insert a node at a specific position and the errors I am getting are,
AttributeError: 'NoneType' object has no attribute 'next'
and also
Function missing 2 required positional arguments: 'x' and 'y'
Code:
class SinglyLinkedListNode:
def __init__(self, data):
self.data = data
self.next = None
class SinglyLinkedList:
def __init__(self):
self.head = None
self.tail = None
def insertnode_end(self, data):
node = SinglyLinkedListNode(data)
if not self.head:
self.head = node
else:
self.tail.next = node
self.tail = node
def print_ll(self):
temp = self.head
while temp is not None:
print(temp.data, end=" ")
temp = temp.next
def insertNode_pos(self, data, pos):
new_node = SinglyLinkedListNode(data)
if (pos == 0):
new_node.next = self.head
self.head = new_node
temp = self.head
while temp.next is not None:
for _ in range(pos - 1):
temp = temp.next
new_node.next = temp.next
temp.next = new_node
llist_count = int(input())
llist = SinglyLinkedList()
for _ in range(llist_count):
llist_item = int(input())
llist.insertnode_end(llist_item)
data = int(input())
pos = int(input())
llist.insertNode_pos(data, pos)
llist.print_ll()
I don't see x and y in your code. It is helpful if you include the full traceback. It seems that your function is hitting the last node in the list, whose next item is None. Obviously, None doesn't have the next and data attributes.
Meanwhile, I modified your insertNode_pos function. One important line here is return if pos == 0. Your function doesn't need to continue in that case.
def insertNode_pos(self, data, pos):
new_node = SinglyLinkedListNode(data)
if pos == 0:
new_node.next = self.head
self.head = new_node
return
temp = self.head
for iter in range(pos):
if iter == 0:
temp = self.head
else:
temp = temp.next
new_node.next = temp.next
temp.next = new_node
One more note is that implementing __str__ is a more common practice for printing content of your data:
def __str__(self):
output = []
temp = self.head
while temp is not None:
output.append(str(temp.data))
temp = temp.next
return ",".join(output)
Then you can simply say print(llist)

Node getting added twice into list

This is my code ignore if any of the spacing is wrong the code works perfectly fine in python.
class Node:
def __init__(self, value):
self.value = value
self.next = None
def __str__(self):
return "Node({})".format(self.value)
def getNext(self):
return self.next
def getValue(self):
return self.value
def setNext(self, new_next):
self.next = new_next
def setValue(self, new_value):
self.value = new_value
__repr__ = __str__
class OrderedLinkedList:
def __init__(self):
self.head=None
self.tail=None
self.count = 0
def __str__(self):
temp=self.head
out=[]
while temp:
out.append(str(temp.value))
temp=temp.next
out=' '.join(out)
return ('Head:{}\nTail:{}\nList:{}'.format(self.head,self.tail,out))
__repr__=__str__
def add(self, value):
#write your code here
if self.head == None:
new_node = Node(value)
self.head = new_node
self.tail = self.head
self.head.setNext(self.tail)
if self.head.value > value:
new_node = Node(value)
new_node.value = value
new_node.next = self.head
self.head = new_node
else:
new_node = Node(value)
self.tail.setNext(new_node)
self.tail = new_node
self.count += 1
def pop(self):
#write your code here
if self.head == None:
return 'List is empty'
if len(self) == 1:
value = self.head.getValue()
self.head = None
self.tail = None
self.count = 0
return value
current = self.head
while current.next is not self.tail:
current = current.getNext()
value = self.tail.getValue()
self.tail = current
self.tail.next = None
self.count -= 1
return value
def isEmpty(self):
#write your code here
return self.head == None
def __len__(self):
#write your code here
return self.count
The only problem I have with it is that when I first use the function add it adds the number twice. Below is the outcome when I first call add every time after that it adds the number only once. How can I fix it so it only adds the first number once instead of twice.
>>> x=OrderedLinkedList()
>>> x.add(2)
>>> print(x)
Head:Node(2)
Tail:Node(2)
List:2 2
add(item) adds a new Node with value=item to the list making sure that the ascending order is preserved. It needs the item and returns nothing.
Yep, it adds the first number twice since you need fix a bug in your add method by adding an elif:
def add(self, value):
if self.head == None:
new_node = Node(value)
self.head = new_node
self.tail = self.head
# self.head.setNext(self.tail) ## remove to prevent infinity loop
elif self.head.value > value:
new_node = Node(value)
new_node.value = value
new_node.next = self.head
self.head = new_node
else:
new_node = Node(value)
self.tail.setNext(new_node)
self.tail = new_node
Since, if the head es None once the data is added then the next conditional always will execute one of the two parts on if or else.

Remove method in Python LinkedList using an index

class Node(object):
def __init__(self, data, next):
self.data = data
self.next = next
class LinkedList(object):
head = None
tail = None
def print_list(self):
node = self.head
while node:
print node.data,
node = node.next
def add_front(self, data):
node = Node(data, None)
if self.head is None:
self.head = self.tail = node
else:
self.tail.next = node
self.tail = node
def remove(self, index):
curr_node = self.head
prev_node = None
while curr_node and index>=0:
if index == 0:
if prev_node is not None:
prev_node.next = curr_node.next
else:
self.head = curr_node.next
index = index - 1
prev_node = curr_node
curr_node = curr_node.next
So, I wanted to implement a remove method using index in python but it does not seem to be working. I think I'm messing something with replacing the nodes but can't figure out which one. So a little help needed here.

NoneType Error: Python Doubly Linked List

Getting caught up in a solution to NoneType errors stemming from using my functions add and append in the below code to an empty Double_list class object. Best way to avoid?
class Dbl_Node:
def __init__(self, data):
self.data = data
self.next = None
self.prev = None
class Double_list:
def __init__(self): # Creates initial list w/ head and tail as None
self.head = None
self.tail = None
def add(self, item): # adds node to beginning/head of list
temp = self.head
self.head = Dbl_Node(item)
temp.prev = self.head
self.head.next = temp
def append(self, item): # adds node to end/tail of list
temp = self.tail
self.tail = Dbl_Node(item)
self.tail.prev = temp
temp.next = self.tail
You're initialising head and tail to None, but then trying to set prev and next members on them when inserting the first Dbl_Node.
def add(self, item):
temp = self.head # on the first call to "add", self.head is None
# (as set in __init__) so temp is now None
self.head = Dbl_Node(item) # create a new node and assign it to self.head
# this is fine
temp.prev = self.head # this says assign the new node in self.head to the "prev"
# member of temp, however temp is None so the temp.prev part
# throws the error
You should check for this case
def add(self, item): # adds node to beginning/head of list
temp = self.head
self.head = Dbl_Node(item)
if temp is not None:
temp.prev = self.head
An alternate solution is to start with "dummy" nodes for the head and tail:
def __init__(self):
self.head = Dbl_Node(None)
self.tail = Dbl_Node(None)
self.head.next = self.tail
self.tail.prev = self.head
And then insert items in between these nodes
def add(self, item):
temp = self.head.next
self.head.next = Dbl_Node(item)
temp.prev = self.head.next
self.head.next.next = temp
Although I find this tends to needlessly complicate things a bit.
def append(self, item): # adds node to end/tail of list
temp = self.tail
self.tail = Dbl_Node(item)
self.tail.prev = temp
temp.next = self.tail
This will always raise a NoneType exception because
self.tail is initially None then you assign a reference
to it (None) to temp and try to assign something to
None. Won't work.
YOu need to probably firstly assign a new object reference to self.tail

Categories

Resources