Linked List Implementation Error In Python - python

So I was trying to make a Linked List in python, but I'm getting this error:
If currentNode.nextNode is None:
AttributeError: 'str' object has no attribute 'nextNode'
Not sure why I get that as currentNode.nextNode should have a .nextNode attribute just like every other node.
Here's the code:
class linkedListNode:
def __init__(self, value, nextNode=None):
self.value=value
self.nextNode=nextNode
class linkedList():
def __init__(self, head=None):
self.head=head
def insert(self, value):
node=linkedListNode(value)
if self.head==None:
self.head=node
return
currentNode = self.head
while True:
if currentNode.nextNode is None:
currentNode.nextNode=node
break
currentNode = currentNode.nextNode
def printLinkedList (self):
curNode=self.head
while curNode!=None:
print(curNode.value)
curNode=curNode.nextNode
#Just testing out the linked list below to see if it works:
ll=linkedList("10")
ll.insert("50")
ll.insert(4)
ll.insert(6)
ll.insert(3)
ll.insert(1)
ll.printLinkedList()

The way you defined linkedList, it expects an instance of linkListNode as an argument, not a value.
ll = linkedList(linkedListNode("10"))

When you initialize the linkedList object you are passing a string as a parameter:
ll=linkedList("10")
As a result self.head will be equal to string "10"

Related

how is the object using a variable which is not inside the class or defined anywhere

In this code the object of class Node is using a variable next which is not defined anywhere and the code is still working HOW?How is the object using a variable which is not defined in its class
class Node:
def __init__(self, data):
self.data = data
class LinkedList:
# Function to initialize head
def __init__(self):
self.head = None
# Function to reverse the linked list
def reverse(self):
prev = None
current = self.head
while(current is not None):
next = current.next
current.next = prev
prev = current
current = next
self.head = prev
# Function to insert a new node at the beginning
def push(self, new_data):
new_node = Node(new_data)
new_node.next = self.head
self.head = new_node
# Utility function to print the linked LinkedList
def printList(self):
temp = self.head
while(temp):
print(temp.data)
temp = temp.next
llist = LinkedList()
llist.push(20)
llist.push(4)
llist.push(15)
llist.push(85)
print( "Given Linked List")
llist.printList()
llist.reverse()
print ("\nReversed Linked List")
llist.printList()
While in most strongly typed languages this is not possible, Python allows instance attributes to be defined even after the instance has been created and the constructor has run. As long as code does not reference an attribute before it has been defined, there is no issue. See also: Can I declare Python class fields outside the constructor method?
In this particular case the following code would produce an error:
node = Node(42)
if node.next: # Attribute error
print("42 is not the last node")
else:
print("42 is the last node")
However, the only place where new node instances are created is in the push method of the LinkedList class:
def push(self, new_data):
new_node = Node(new_data)
new_node.next = self.head
self.head = new_node
As you can see, the next attribute is defined immediately after the node is constructed. So in practice, every node in a linked list will have a next attribute.
Best Practice?
It is open for debate whether this coding practice is advisable. For instance, Pylint has a rule defining-attr-methods which by default will raise a warning when attributes are defined outside of __init__, __new__, setUp, or __post_init__.
Alternative
In this scenario I would certainly prefer to define the next attribute in the constructor, and give the constructor an extra, optional parameter with which next can be initialised:
class Node:
def __init__(self, data, nxt=None):
self.data = data
self.next = nxt
With this change, the push method of the LinkedList class can be reduce to just:
class LinkedList:
# ...
def push(self, new_data):
self.head = Node(new_data, self.head)
That looks a lot more elegant.
Unrelated, but I would also let the constructor of LinkedList accept any number of values to initialise the list with:
class LinkedList:
def __init__(self, *values):
self.head = None
for value in reversed(values):
self.push(value)
Now the main code could create a list with 4 values in one go:
llist = LinkedList(85, 15, 4, 20)

How to call a function and receive parameter in a function outside a linked list class using variables present in linked list

I am using two python files, one file in which a class of linked list present and another file is the one in which I am importing first file so that I can use linked list I built in first file. The second file is for reverse file. I have already done reverse using iteration part, now trying to build a code for reverse using recursion and for that I am calling and passing arguments inside function but something did not work out and it is showing TypeError like this function has no arguments.
Please check it out my code followed by error
Second file
from code.linkedlist import *
llist=linkedlist()
llist.appendnodesatbegin(23)
llist.appendnodesatbegin(45)
llist.appendnodesatbegin(67)
llist.appendnodesatbegin(12)
llist.appendnodesatbegin(-11)
llist.appendnodesatbegin(0)
print ("Before reverse")
llist.display()
def reverseiterative():
llist.current = llist.head
llist.prev = None
while (llist.current):
llist.next = llist.current.next
llist.current.next = llist.prev
llist.prev = llist.current
llist.current = llist.next
llist.head = llist.prev
reverseiterative()
print("After the reverse of list using iterative method")
llist.display()
llist.p=llist.head
llist.prev=None
def reverserecursive(p,prev):
next1=llist.p.next
p.next=prev
if llist.next1 is None:
return
else:
reverserecursive(next1,p)
reverserecursive(llist.p,llist.prev)
print("After the reverse of list using recursive method")
llist.display()
first file:
class node:
def __init__(self,data):
self.data=data
self.next=None
class linkedlist:
def __init__(self):
self.head=None
self.last_pointer=None
def appendnodesatbegin(self,data):
newnode=node(data)
if(self.head==None):
self.head=newnode
self.last_pointer=newnode
else:
self.last_pointer.next=newnode
self.last_pointer=self.last_pointer.next
def appendnodesatend(self,data):
newnode=node(data)
newnode.next=self.head
self.head=newnode
def appendatmid(self,prev,new):
temp=self.head
newnode=node(new)
while(temp):
if(temp.data==prev):
newnode.next=temp.next
temp.next=newnode
temp=temp.next
def display(self):
temp=self.head
while(temp):
print(temp.data)
temp=temp.next
#def reversedisplay(self):
error is
reverseiterative(llist.p,llist.prev)
TypeError: reverseiterative() takes no arguments (2 given)
reverseiterative as defined:
def reverseiterative():
takes no argument, you are calling it with 2.
You were probably supposed to call reverserecursive given the arguments you passed and the argument's in the function signature:
def reverserecursive(p,prev):
Your function doesn't take any parameters in it's deceleration:
reverseiterative(foo, bar):
This (or whatever values you wish to process) will fix it.
from code.linkedlist import *
llist=linkedlist()
llist.appendnodesatbegin(23)
llist.appendnodesatbegin(45)
llist.appendnodesatbegin(67)
llist.appendnodesatbegin(12)
llist.appendnodesatbegin(-11)
llist.appendnodesatbegin(0)
print ("Before reverse")
llist.display()
def reverseiterative(self):
self.current = self.head
self.prev = None
while (self.current):
self.next = self.current.next
self.current.next = self.prev
self.prev = self.current
self.current = self.next
self.head = self.prev
llist.reverseiterative=reverseiterative
llist.reverseiterative()
print("After the reverse of list using iterative method")
llist.display()
def reverserecursive(self,p,prev):
next=p.next
p.next=prev
if next is None:
return
else:
self.reverserecursive(next,p)
llist.p=llist.head
llist.prev=None
llist.reverserecursive(llist.p,llist.prev)
print("After the reverse of list using recursive method")
llist.display()
Here is the second part to fix your issue:
class node:
def __init__(self,data):
self.data=data
self.next=None
class linkedlist:
def __init__(self):
self.head=None
self.last_pointer=None
def appendnodesatbegin(self,data):
newnode=node(data)
if(self.head==None):
self.head=newnode
self.last_pointer=newnode
else:
self.last_pointer.next=newnode
self.last_pointer=self.last_pointer.next
def appendnodesatend(self,data):
newnode=node(data)
newnode.next=self.head
self.head=newnode
def appendatmid(self,prev,new):

Python: How to check if an input is an instance of a class within that class?

I tried to write a code that protects the pointer of a linked list. The setter should point only to an instance which belongs to the same class. Usually isinstance() or type() work after the class is defined. But the setter is a method inside that class, hence the class is not fully defined yet.
I have no doubt that type() gives out error. But I wonder why isinstance(instance, class) yields False if calling from another class.
#define the Node class
class Node:
"""Class Node contain only data and a next pointer variables."""
def __init__(self, Data = None):
self.data = Data
self.__next = None
def getNext(self):
"""The getter"""
return self.__next
def setNext(self, NextNode):
"""The setter"""
#if possible check if NewNode is an instance of Node before pointing to it.
#I have tried "isinstance(), type(), etc. but failed.
if isinstance(NextNode, Node):
self.__next = NextNode
else:
print('The Next pointer should point to "Node" only.')
Then check if isinstance is working
ANode = Node((1,2,3))
BNode = Node((5,6))
ANode.setNext(BNode)
print(BNode)
print(ANode.getNext())
Both prints yield the same address
<__main__.Node object at 0x112162828>
<__main__.Node object at 0x112162828>
So everything looks fine. But When I call from the LinkedList class, printed below, the isinstance yields False, as seen from my warning.
class LinkedList:
"""This class is the Linked List of Node."""
def __init__(self, FirstNode = None):
"""Initialize by creating an empty List. __First hold the pointer that point to the first node."""
if FirstNode is None:
self.__first = Node(None)
self.__last = self.__first
elif type(FirstNode) is Node:
self.__first = FirstNode
self.__last = self.__first
else:
print('To create a linked-list enter nothing or a Node.')
raise TypeError
def getFirst(self):
return self.__first
def append(self, NewLastNode):
"""Add LastNode to the end of the list."""
if not isinstance(NewLastNode,Node):
raise TypeError
OldLast = self.__last
OldLast.setNext(NewLastNode)
self.__last = NewLastNode
NewLastNode.setNext(None)
def removeFirstNode(self):
"""Remove the first node (when the buffer is full)."""
OldFirst = self.__first
NewFirst = OldFirst.getNext()
if NewFirst == None:
# just clear data
OldFirst.data = None
else:
self.__first = NewFirst
del OldFirst
Then I create an instance of the LinkedList class
LL = LinkedList(Node((1,2)))
NewNode = Node((2.0, 3.0, -10))
Surely isinstance works fine here
isinstance(NewNode,Node)
yields True, but
LL.append(NewNode)
which will call Node.setNext() and there the isinstance() yields False as the else in Node.setNext() prints out
The Next pointer should point to "Node" only.
The piece of code that's giving you the error is this:
NewLastNode.setNext(None)
because you're trying to set the next element to an object that it's not a Node instance, hence the error.
I think you could simply remove this statement, as your self.__last is now correctly pointing to your NewLastNode. So your code will become:
def append(self, NewLastNode):
"""Add LastNode to the end of the list."""
if not isinstance(NewLastNode,Node):
raise TypeError
OldLast = self.__last
OldLast.setNext(NewLastNode)
self.__last = NewLastNode

object has no attribute error in python

I am new to python programming and I have encountered an error for the below mentioned program. It is a simple program to add a node to the end of the linked list. The error says object LinkedList has no attribute head. Please Help me with the problem.
class Node:
def _init_(self, data):
self.data = data
self.next = None
class LinkedList:
def _init_(self):
self.head=None
def createNode(self, data):
newNode = Node(data)
return newNode
def insertNodeHelper(self, head, data):
if(head==None):
return self.createNode(data)
head.next = self.insertNodeHelper(head.next,data)
return head
def insertNode(self, data):
self.head = self.insertNodeHelper(self.head,data)
def printList(self, head):
if(head==None):
return;
print(head.data)
self.printList(head.next)
def printLinkedList(self):
self.printList(self.head)
l = LinkedList()
l.insertNode(12)
l.insertNode(13)
l.insertNode(15)
l.printList()
I am getting the following error:
Message File Name Line Position
Traceback
<module> <module1> 35
insertNode <module1> 21
AttributeError: 'LinkedList' object has no attribute 'head'
Change def _init_(self): to def __init__(self):(two underscore). Because this method is a constructor method, it must be writen in this form.

python int object is not callable?

Relatively new to Python.
I'm trying to practice linked list but I'm stuck with an error and couldn't figure out what the issue is.
The error:
self.assertEqual(l.size(), 1)
TypeError: 'int' object is not callable
The code:
from node import Node
class List:
def __init__(self):
self.head = None
self.size = 0
def add(self, item):
temp = Node(item)
temp.setNext(self.head) # ERROR ON THIS LINE
self.head = temp
size += 1
def size(self):
return self.size
...
Node:
class Node:
def __init__(self, data):
self.data = data
self.next = None
....
Test:
import unittest
import unorderedlist
class TestUnorderedList(unittest.TestCase):
def test_add(self):
l = unorderedlist.List()
l.add(8)
self.assertEqual(l.size(), 1)
if __name__ == '__main__':
unittest.main()
It's funny because if I rename the size() to len and call it like l.len() it works fine. Anyone have a clue?
With the line self.size = 0 you hide the methode size, so size is an int and not a method anymore.
You have hidden your method with the attribute.
In your code you are then accessing the attribute which is of type int and so not callable.
Avoid to name methods and attributes the same.
In case you want to achieve properties. There is the #property decorator:
#property
def size(self):
return self._size
In your constructor you just define self._size and work internally with it.

Categories