AttributeError: 'NoneType' object has no attribute 'data' in displaying linked list - python-3.x

I'm trying to display linked list elements in the form of a list but keep getting this error:
AttributeError: 'NoneType' object has no attribute 'data'
class Node:
def __init__(self,data=None,next=None):
self.data = data
self.next = next
class LinkedList:
def __init__(self):
self.head = None
def insert_at_beginning(self,data):
node = Node(data,self.head)
self.head = node
def display(self):
elements = []
currNode = self.head
while currNode:
currNode = currNode.next
elements.append(currNode.data)
print(elements)
if __name__ == "__main__":
ll = LinkedList()
ll.insert_at_beginning(1)
ll.insert_at_beginning(2)
ll.insert_at_beginning(3)
ll.display()
Can anyone explain the error here?

After the while loop, append data first then go to the next. You're getting the error because if currNode.next is null then it's showing the object has no attribute 'data'. So, append first then go to next. If currNode.next is null then the loop will stop.
while currNode:
elements.append(currNode.data)
currNode = currNode.next

Related

Wrapper Class in Python for Linked List

I am absolutely new to Wrapper Classes in Python. I was trying to implement it in a program of linked list where multiple linked list are in use. My code is:
def nodewrap(cls):
class Nodewrap:
def __init__(self):
self.head = None
self.tail = None
return Nodewrap
#nodewrap
class Node:
def __init__(self,data):
self.data = data
self.next = None
class Intersection:
def addnode(self,d):
newnode = Node(d)
if head == None:
head = tail = newnode
else:
tail.next = newnode
tail = newnode
obj1 = Intersection()
obj2 = Intersection()
obj3 = Intersection()
s1 = int(input("Enter size of 1st list : \n"))
for i in range(s1):
obj1.addnode(int(input("Enter the data : \n")))
s2 = int(input("Enter size of 1st list : \n"))
for i in range(s2):
obj2.addnode(int(input("Enter the data : \n")))
temp1 = obj1.head
for i in range(s1):
temp2 = obj2.head
for j in range(s2):
if temp1.data == temp2.data:
obj3.addnode(temp1.data)
break
temp2 = temp2.next
temp1 = temp1.next
print("Intersection is :")
temp = obj3.head
while temp!=None:
print(temp.data,end=" ")
temp = temp.next
I thought of using a wrapper class to wrap the class Node instead of using objects of the class Intersection only with data fields as head, tail. But it is giving me some sort of error with regards to init().
Please help.
I was trying to learn it from here:
https://www.geeksforgeeks.org/wrapper-class-in-python/
I think I understand what you want to do, but I think that you don't want to use a decorator, but you want to inherit from NodeWrap class
class Nodewrap:
head = None
tail = None
class Node(NodeWrap):
def __init__(self,data):
self.data = data
self.next = None
But I don't see any reason why to inherit this way. This should be enough, for a linked list. I have added is_first and is_last property
from __future__ import annotations
class Node:
prev_node = None
next_node = None
def __init__(self, data):
self.data = data
def add_node(self, node: Node) -> None:
if self.prev_node is not None:
raise ValueError('Previous node already defined.')
self.next_node = node
node.prev_node = self
#property
def is_first(self) -> bool:
return self.prev_node is None
#property
def is_last(self) -> bool:
return self.next_node is None
You can implement next, iter and create an Iterator class.
I don't recommend using next as the variable name.
from __future__ import annotations reference here. It's just for self reference annotation.

AttributeError: 'LinkedList' object has no attribute 'head'

I don't understand what is wrong with my code. it says
AttributeError: 'LinkedList' object has no attribute 'head'
Here is my code:
class Node:
def __init__(self, data):
self.data = data
self.next = None
I created an empty linked list and added nodes:
class LinkedList():
def __int__(self):
self.head = None
def insert(self, newNode):
if self.head is None:
self.head = newNode
else:
#head =>john->Ben->Matthew->None
lastNode = self.head
while True:
if lastNode.next is None:
break
lastNode = lastNode.next
lastNode.next = newNode
def printList(self):
#head=>john->Ben->Matthew->None
currentNode = self.head
while True:
if currentNode is None:
break
print(currentNode.data)
currentNode = currentNode.next
# node => data, next
#firstnode.data => data, firstnode.next => None
firstNode = Node('john')
linkedlist = LinkedList()
linkedlist.insert(firstNode)
secondNode = Node('Ben')
linkedlist.insert(secondNode)
thridNode = Node('Matthew')
linkedlist.insert
linkedlist.printList()
You have some errors which you could easily spot with some debugging (stepping through the code):
The LinkedList function __int__ is never executed (you could spot this by putting a breakpoint there). It should be named __init__.
The main program does not add the third node, because it does not call the insert method -- it merely references it. You could spot this easily when stepping through the code, one instruction at a time, with a debugger. Add the parentheses and pass the argument.
The printList has a loop that runs infinitely, because the line that moves the currentNode reference is not part of the loop's body. You could spot this easily again by stepping through the code with a debugger. This statement should be indented more to become part of the loop.
This should fix your problems.
Note: this was just a matter of debugging. You really can do this yourself in a good programming environment.

Why are class nodes not saving children outside of method call? Python

The Repo:
https://github.com/icarus612/mazeRunner-PY/tree/stack-overflow
The issue: I don't know why the the nodes are not saving their children outside the runner method call.
The project: Im building a maze runner with several classes, a node class for storing spots in the maze, a maze class to take in mazes and evaluate what are walls and what are spaces, and a runner class to map the maze, find if there is a route possible and then solve for the route. There is also a solver script to take in command line inputs. originally I had built a working "runner" but it wasn't giving the proper route, so I went back to the drawing board (if someone can tell me way the runner isn't giving the proper route that would be cool too but thats not the question at hand)
Why are the nodes not saving there children outside the method?
The code here will be an abridged version just for what the issue Im running into is.
Node class:
class Node:
def __init__(self, value):
self.value = value
self.children = []
self.visited = []
def add_visited(self, node):
self.visited.append(node)
def add_child(self, child_node):
self.children.append(child_node)
def add_path(self, node_path):
if not self.path:
self.path = node_path
else:
self.path = self.path if len(self.path) < len(node_path) else node_path
def remove_child(self, child_node):
self.children.discard(child_node)
Runner Class:
class Runner:
def __init__(self, maze):
self.open_nodes = []
self.visited = []
self.start = None
self.end = None
self.maze = maze
self.completed = False
self.mapped_maze = []
self.node_paths = []
self.find_end_points()
self.get_open_nodes()
def get_open_nodes(self):
p = self.maze.layout
for x in range(len(p)):
for y in range(len(p[x])):
if p[x][y] != self.maze.wall_char:
self.open_nodes.append(Node((x, y)))
for i in self.open_nodes:
self.look_around(i)
print(i.children) #should print something !and does!:)
def find_end_points(self):
for x in range(len(self.maze.layout)):
for y in range(len(self.maze.layout[x])):
p = self.maze.layout[x][y]
if p == self.maze.start_char:
self.start = Node((x, y))
elif p == self.maze.end_char:
self.end = Node((x, y))
def look_around(self, node):
for i in self.open_nodes:
if i.value[0]-1 == node.value[0] and i.value[1] == node.value[1]:
node.add_child(i)
if i.value[0]+1 == node.value[0] and i.value[1] == node.value[1]:
node.add_child(i)
if i.value[1]-1 == node.value[1] and i.value[0] == node.value[0]:
node.add_child(i)
if i.value[1]+1 == node.value[1] and i.value[0] == node.value[0]:
node.add_child(i)
def make_node_paths(self, point=None):
if point == None:
point = self.start
print(point.value, point.children)
for i in point.children:
if i.value not in point.visited:
point.add_visited(point.value)
if point.value == self.end.value:
self.node_paths.append(point.path)
self.completed = True
self.make_node_paths(i)
Maze Class:
class Maze:
def __init__ (self, layout=None, start_char="s", end_char="e", wall_char="#", open_char=" ", build=(10, 10)):
self.wall_char = wall_char
self.start_char = start_char
self.end_char = end_char
self.open_char = open_char
self.layout = layout
if layout:
self.width = len(layout[0])
self.height = len(layout)
else:
self.build_new(build[0], build[1])
Solver script:
maze = Maze(build=(20, 20))
runner = Runner(maze)
print(runner.start.value, runner.start.children) #point that should be logging something !but doesnt!:(
runner.make_node_paths()
complete = "Yes" if runner.completed else "No"
print(f"Is maze possible? {complete}")
Console for the two print statements:
[<node.Node object at 0x101060780>] #what runner.start.children should be
[<node.Node object at 0x1010604a8>, <node.Node object at 0x100d253c8>]
[<node.Node object at 0x1010604e0>, <node.Node object at 0x1010606d8>]
[<node.Node object at 0x1010604a8>, <node.Node object at 0x100d25400>]
[<node.Node object at 0x100d25470>]
[<node.Node object at 0x1010601d0>, <node.Node object at 0x100d254a8>]
[<node.Node object at 0x1010604e0>, <node.Node object at 0x100d25518>]
[<node.Node object at 0x1010606d8>, <node.Node object at 0x100d25438>, <node.Node object at 0x100d25588>]
[<node.Node object at 0x100d25400>, <node.Node object at 0x100d25470>]
[<node.Node object at 0x101060710>, <node.Node object at 0x100d25438>, <node.Node object at 0x100d255c0>]
[<node.Node object at 0x101060780>, <node.Node object at 0x100d254e0>]
[<node.Node object at 0x100d254a8>, <node.Node object at 0x100d25518>]
[<node.Node object at 0x100d253c8>, <node.Node object at 0x100d254e0>, <node.Node object at 0x100d25550>]
[<node.Node object at 0x100d25518>, <node.Node object at 0x100d25588>]
[<node.Node object at 0x100d25400>, <node.Node object at 0x100d25550>]
[<node.Node object at 0x100d25470>]
(1, 1) [] #runner.start.value and what runner.start.children comes in as
other notes:
I haven't included some of the runner class and most of the solver script that gets inputs and most of the maze script that builds a maze. The issue Im having is that when i make nodes and give those nodes children the save in the initial method, as you can see logged out, but then when i try to log it out in the next line of my solver function i get diddly squat. I don't even know what type of issue Im looking at here. Is this memory or something wrong with the way i'm saving them? i tried to switch them from in sets to in arrays but that didn't work, either. It seems to work if its all inside the same method but not if its in 2 separate methods. its like the its losing those children after it exits the method.
Update:
I found this link which sort of answers my question without Really giving an answer: nested classes in Python
after reading this Im wondering if i need to make the classes extend each other in some way? it provides insight into what might be going on without really giving an answer on how i could fix my issue, and Im not working with extended classes. I have tried finding ways to make sure the copy is a deep copy but even when using copy.deepcopy the code stays the same
The issue is in how i was saving self.start and self.end in the find_end_points function.
def find_end_points(self):
def check(node_val):
if node_val not in [i.value for i in self.open_nodes]:
node = Node(node_val)
else:
for i in self.open_nodes:
if i.value == node_val:
node = i
return node
for x in range(len(self.maze.layout)):
for y in range(len(self.maze.layout[x])):
p = self.maze.layout[x][y]
if p == self.maze.start_char:
self.start = check((x, y))
elif p == self.maze.end_char:
self.end = check((x, y))
is the new function and now i get the proper start and end values as well as the children that were saved to them. This is not an issue with global or local variable saving in a method.

AttributeError: 'int' object has no attribute 'data'

I was trying to implement some basic operations of Binary search tree in Python3.7. I have just started coding problems from Hackerrank and I got stuck while implementing levelOrder traversal in BST. What should I do to resolve this AttributeError: 'int' object has no attribute 'data'?
I am using queue to solve this problem, initially, the queue will point to root node, then checks for left and right children. If found, the children will get append to the queue and the process continues until the queue is empty. I am popping out the first element in each iteration and storing it in temp variable. This way i will get nodes at each level of tree.
class Node:
def __init__(self, data):
self.data = data
self.leftChild = None
self.rightChild = None
def insert(self, data):
if self.data is not None:
if data < self.data:
if self.leftChild is None:
self.leftChild = Node(data)
else:
self.leftChild.insert(data)
elif data > self.data:
if self.rightChild is None:
self.rightChild = Node(data)
else:
self.rightChild.insert(data)
else:
self.data = data
def traverseLevelOrder(self):
queue = []
queue.append(self.data)
while queue:
# Print front of queue and remove it from queue
print(queue[0].data)
temp = queue.pop(0)
# Enqueue left child
if temp.leftChild is not None:
queue.append(temp.leftChild)
# Enqueue right child
if temp.rightChild is not None:
queue.append(temp.rightChild)
class BST:
def __init__(self):
self.rootNode = None
def insert(self, data):
if self.rootNode is None:
self.rootNode = Node(data)
else:
self.rootNode.insert(data)
def traverseLevelOrder(self):
if self.rootNode is None:
return
else:
self.rootNode.traverseLevelOrder()
bst = BST()
bst.insert(2)
bst.insert(4)
bst.insert(1)
bst.insert(3)
bst.traverseLevelOrder()
The code should return the level traversal order like one given below(within a level it should print first left node then right node):
2
1
4
3
Instead, I am having the below error:
Traceback (most recent call last):
print(queue[0].data)
AttributeError: 'int' object has no attribute 'data'
You're appending an integer, self.data to the queue, then attempting to access a property on the integer with queue[0].data, causing the AttributeError to be raised.
Instead, append the node itself with:
queue.append(self)
queue.append(self.data)
Did you mean:
queue.append(self)
?
Right now you're only adding a number to the queue, not the whole object.

Stack pop using linked list - Python

I am trying to pop an item off a stack (using a linked list as oppose to an array). I first created a LinkedList class with 3 nodes with the values [1,2,3]. So I would like pop off the last node (node_C, value=3), therefore I expect to see the values [1,2]. Instead nothing prints out.
class LinkedList:
def __init__(self, value):
self.value = value
self.next = None
node_A = LinkedList(1)
node_B = LinkedList(2)
node_C = LinkedList(3)
node_A.next = node_B
node_B.next = node_C
def pop(head):
current_node = head
while current_node.next:
if current_node.next == None:
break
else:
current_node = current_node.next
del current_node
return node_A.value, node_B.value, node_C.value
try:
print(pop(node_A))
except NameError:
pass
How can I rewrite this to achieve my desired results (i.e. show values 1,2 .. with 3 popped off)?
The del current node and return node_A.value, node_B.value, node_C.value
commands should belong to the pop function, so they should be intended. But anyway the del current node doesnt work for me. Instead you could write current_node.value = None but then you still return all 3 node values so the result would be 1,2,None.
I would rather write the pop function inside the class and add another printlist function to the class as well. The pop function just removes the last element from the list (changes the next attribute to None for the 2nd last element in the list) and doesn't print or return anything. The printlist function iterates through the list and prints out all elements (while there are next elements). Here is my code:
class LinkedList:
def __init__(self, value):
self.value = value
self.next = None
def pop(self):
current_node = self
while current_node.next:
if current_node.next.next == None:
current_node.next = None
else:
current_node = current_node.next
def printlist(self):
current_node = self
lst = [current_node.value]
while current_node.next:
current_node = current_node.next
lst.append(current_node.value)
print lst
node_A = LinkedList(1)
node_B = LinkedList(2)
node_C = LinkedList(3)
node_A.next = node_B
node_B.next = node_C
try:
node_A.pop()
node_A.printlist()
except NameError:
pass
If I run this, the result is [1,2]. If I remove the node_A.pop() I get [1,2,3]. If I write another node_A.pop() then result is [1]
I guess I have found the issue with your logic, so based on the code provided it seems that pop function doesn't return anything, may be it's just formatting or something else.
But here is the correct version of your code, where I just delete the last node in the pop method and I call another method called listValues which returns me with the node values that exist in the linked list after pop
Look at the below implementation for a clearer view.
class LinkedList:
def __init__(self, value):
self.value = value
self.next = None
node_A = LinkedList(1)
node_B = LinkedList(2)
node_C = LinkedList(3)
node_A.next = node_B
node_B.next = node_C
def pop(head):
current_node = head
while current_node.next:
if current_node.next == None:
del current_node
break
else:
current_node = current_node.next
def listValues(head):
values = []
current_node = head
while current_node.next:
values.append(current_node.value)
current_node = current_node.next
return values
try:
pop(node_A)
print(listValues(node_A))
except NameError:
pass
Hope this helps!

Resources