AttributeError: 'str' object has no attribute 'insert' - python

I'm trying to insert a piece of text into my linked list. However, when ever I try to do this I get an error "AttributeError: 'str' object has no attribute 'insert'". I am writing this in python 3.3.
class Node:
def __init__(self, item= None , link= None ):
self.item = item
self.next = link
def __str__(self):
return str(self.item)
class List:
def __init__(self):
self.head = None
self.count = 0
def is_empty(self):
return self.count == 0
def is_full(self):
return False
def reset(self):
self.__init__()
def __len__(self):
return self.count
def _getNode(self, index):
node = self.head
for _ in range(index):
node = node.next
return node
def insert(self, index, item):
if index < 0:
index = 0
elif index > len(self):
index = len(self)
if index == 0:
self.head = Node(item, self.head)
else:
node = self._getNode(index - 1)
node.next = Node(item, node.next)
self.count += 1
def delete(self, index):
if self.is_empty():
raise IndexError("List is empty")
if index < 0 or index >= len(self):
raise IndexError("Index is out of range")
if index == 0:
self.head = self.head.next
else:
node = self._getNode(index - 1)
node.next = node.next.next
self.count -= 1
import LinkedList
text= LinkedList.List()
def insert_num(line,text):
text.insert(line - 1,text)
def delete_num(line):
if line is None:
text.reset
else:
text.delete(line)
def print_num(line):
if line is None:
i= 0
while i< line.count:
item= text._getNode(i)
print (item)
else:
print(text._getNode(line))
while True:
print("1. Insert")
print("2. Delete")
print("3. Print")
print("4. Quit")
command = int(input())
if command == 1:
line = int(input("At what line do you wish to insert your text?: "))
text = input("Text: ")
insert_num(line,text)
elif command == 2:
line = int(input("What line do you wish to delete?: "))
delete_num(line)
elif command == 3:
line = int(input("What line do you wish to print?: "))
elif command == 4:
break
else:
print("invalid input, please select one of the following numbers:")

In your main loop, you call insert_num(line, text). But text here is the text string you inputted above, not the global variable text which is an instance of your LinkedList class. As the error says, strings don't have an insert method (because they are immutable).

You call these two lines
text = input("Text: ")
insert_num(line,text)
The resulting text variable will be type str, not a linked list. Strings do not have an insert, as the error is telling you.
And when you call these two lines:
import LinkedList
text= LinkedList.List()
That is a different text variable than the one that exists within the scope of your insert_num function.

The problem is variable scoping. When you call your insert_num() procedure you want to insert your new line (the text parameter, which is of type str) into your LinkedList of lines, which is also called text but because the method has a parameter with the same name, this (the linked list) is outside of the scope, and so can't be seen by the procedure.
text= LinkedList.List()
def insert_num(line,text):
text.insert(line - 1,text)
I'd rename the subroutine's parameter:
text= LinkedList.List()
def insert_num(line_number, new_line):
text.insert(line_number - 1,new_line)

.insert() Method can be used with list only, but you are trying to use it with a string. That is why you are getting error

Related

Issues inserting into arbitrary positions (not beginning or end) of doubly linked list

Ok to preface, this is to help with a school assignment. I understand there are unpythonic methods in the following code but this is the format they insist upon. In my insert method I have 4 cases to account for. All of them are dealt with appropriately except for else and im unsure why. For some reason the method insert isn't updating the linked list to include the new_node when this new_node is not placed at the end or start of the list. I'm unsure why this is as at the appropriate position we store the old value of current, we then store its previous and we set current = new_node, we then set new_node's next to be the old value of current and new_node's previous to be the old currents previous. I'm confused as to why this won't work.
class DLinkedListNode:
# An instance of this class represents a node in Doubly-Linked List
def __init__(self,initData,initNext,initPrevious):
self.data = initData
self.next = initNext
self.previous = initPrevious
if initNext != None:
self.next.previous = self
if initPrevious != None:
self.previous.next = self
def getData(self):
return self.data
def setData(self,newData):
self.data = newData
def getNext(self):
return self.next
def getPrevious(self):
return self.previous
def setNext(self,newNext):
self.next = newNext
def setPrevious(self,newPrevious):
self.previous = newPrevious
class DLinkedList:
# An instance of this class represents the Doubly-Linked List
def __init__(self):
self.__head=None
self.__tail=None
self.__size=0
def search(self, item):
current = self.__head
found = False
while current != None and not found:
if current.getData() == item:
found= True
else:
current = current.getNext()
return found
def index(self, item):
current = self.__head
found = False
index = 0
while current != None and not found:
if current.getData() == item:
found= True
else:
current = current.getNext()
index = index + 1
if not found:
index = -1
return index
def add(self, item):
new_node=DLinkedListNode(item,None,None)
new_node.setNext(self.__head)
self.__head=new_node
current=self.__head
new_node.setPrevious(None)
current=current.getNext()
self.__size+=1
def remove(self, item):
# remove the node containing the item from the list
if self.__size == 0:
raise Exception('List is Empty')
current = self.__head
previous = None
found = False
while current != None and not found:
if current.getData() == item:
found = True
else:
previous = current
current = current.getNext()
if not found:
raise Exception('Item not in list')
else:
if previous == None: # the item is in the first node of the list
self.__head = current.getNext()
else: # item is not in the first node
previous.setNext(current.getNext())
self.__size = self.__size -1
def append(self, item):
# adds an item at the end of the list
new_node = DLinkedListNode(item,None,None)
current = self.__head # Start the traversal
if self.__size == 0: # check if list is empty
self.add(item)
else:
while (current.getNext()!=None):
current= current.getNext() # traversing the list
new_node.setNext(None)
new_node.setPrevious(current)
current.setNext(new_node)
self.__size = self.__size +1
def insert(self, pos, item):
# inserts the item at pos
# pos should be a positive number (or zero) of type int
assert type(pos)==int,'Error:pos is not an integer'
assert pos>=0,'Error:pos must be positive'
current=self.__head
new_node= DLinkedListNode(item,None,None)
if pos==0:
self.add(item)
elif pos==self.__size:
self.append(item)
elif pos>self.__size:
raise Exception('Position attempted to enter is larger than the size of linked list.')
else:
current_pos=0
while(current.getNext()!=None):
if (pos)==current_pos:
# storage is a holder variable
storage=current
right=current.getNext()
left=current.getPrevious()
current=new_node
new_node.setPrevious(left)
new_node.setNext(storage)
return True
current=current.getNext()
current_pos+=1
self.__size+=1
# doubly linked list
#Hello(prev)<-->World(store data)-->None
def pop1(self):
current = self.__head
previous = None
while (current.getNext() != None):
previous = current
current = current.getNext()
if (previous == None):
self.__head = None
else:
previous.setNext(None)
self.__size -= 1
return current.getData()
def pop(self, pos=None):
if pos!=None:
assert pos<=self.__size,'Pos must be within list'
assert type(pos)==int,'Pos must be an int'
assert pos>=0,'Pos must not be negative'
current=self.__head
current_pos=0
if pos==(self.getSize()-1) or pos==None:
data_from_method=self.pop1()
return data_from_method
else:
while current.getNext()!=None:
if pos==current_pos:
data=current.getData()
left=current.getPrevious()
right=current.getNext()
left.setNext(right)
right.setPrevious(left)
return data
current_pos+=1
current=current.getNext()
# doubly linked list
#Hello(prev)<-->World(store data)-->None
def searchLarger(self, item):
current=self.__head
current_pos=0
while current.getNext()!=None:
if item<current.getData():
return current_pos
current=current.getNext()
current_pos+=1
return -1
def getSize(self):
return self.__size
def getItem(self, pos):
assert type(pos)==int,'position must be type int'
assert pos<=self.__size,'Position is outside of the list'
current=self.__head
current_pos=0
if pos>=0:
while current!=None:
if current_pos==pos:
return current.getData()
current_pos+=1
current=current.getNext()
else:
current=self.__tail
while current!=None:
if current_pos==pos:
return current.getData()
current_pos-=1
current=current.getPrevious()
def __str__(self):
# returns a string representation of the list
current = self.__head
string = ''
while current != None:
if current.getNext()==None:
string = string + str(current.getData())+''
else:
string=string+str(current.getData())+' '
current = current.getNext()
return string
def test():
new_list=DLinkedList()
for i in range(20):
new_list.insert(i,i)
new_list.insert(1,90)
print(new_list)
test()
You currently have code that links the new node to nodes in the list, but no code that links the existing nodes to the new node. The only gesture you have in that direction is current=new_node, which doesn't achieve anything useful (since current is a local variable and you're about to return from the function).
You probably want something like left.setNext(newnode) and right.setPrevious(newnode), though I'm not sure you've set up both of those variables correctly (one of them should probably be current, unless you're intending to replace an existing node).

I can only push two values onto the stack array?

I can only push two values onto the stack array that I have created when I use the myPush() function. The reason I need to do it this way is because I am not allowed to use the built-in stack functions. Plus I have to use an array not a lit. Thank you.
I can only push two values onto the stack array that I have created when I use the myPush() function. The reason I need to do it this way is because I am not allowed to use the built-in stack functions. Plus I have to use an array not a lit. Thank you.
class Stack:
def __init__(self, data):
if data > 0:
self.stack = [0] * data
self.top = -1
self.stack[self.top] = self.stack[-1]
elif data <= 0:
self.stack = [0] * 10
self.top = -1
def showStack(self):
for i in self.stack:
print(i, end=" ")
return
def isEmpty(self):
return self.stack == []
def myEmpty(self): #complete this function
return # just a placeholder
def push(self, data):
self.stack.append(data)
def myPush(self, data):
if data == 0:
print("You did not enter a value.")
elif self.sizeStack() <= 10:
current = self.stack[stack.top]
self.stack[stack.top] = data
self.stack[stack.top - 1] = current
def pop(self):
data = self.stack[-1]
del self.stack[-1]
return data
def myPop(self): #complete this function
return # just a placeholder
def myPeek(self):
temp = self.top
return temp
def sizeStack(self):
return len(self.stack)
userVal = int(input("Enter the size of the stack: "))
stack = Stack(userVal)
while True:
print('\n1 display the stack')
print('2 add a value to the stack')
print('3 check the value at the top of the stack')
print('4 remove the value at the top of the stack')
print('5 check if the stack is empty')
print('99 quit')
option = int(input("Enter your choice: "))
if option == 1:
stack.showStack()
elif option == 2:
temp = int(input("Enter a number to add to the stack: "))
stack.myPush(temp)
elif option == 3:
print(stack.peek())
elif option == 99:
break
else:
print('Wrong option')
print
try defining a some customized functions that map to your list. Read up on customization here
class stack:
def __init__(self, data):
self.stack = [0] * data
self.top = -1
# whatever you want to do to init the list
def __str__(self): # replaces your showstack function now just use print(stack)
return self.stack
def __iter__(self): # creates an iterator you can use
return iter(self.stack)
def __len__(self): # replaces your sizestack function
return len(self.stack)
basically just adjust the methods you need.

Storing actions in a stack for 'undo' purpose

Because stack allows to either push or pop, it is suitable to redo actions by just simply popping the latest action by the user. I have a stack class where:
class Node:
def __init__(self,item,the_next = None):
self.item = item
self.next = the_next
def __str__(self):
return str(self.item)
class LinkedStack:
def __init__(self):
self.top = None
self.count = 0
def __len__(self):
return self.count
def is_empty(self):
return self.count == 0
def isFull(self):
return False
def reset(self):
self.top = None
self.count = 0
def __str__(self):
current = self.top
ans = ""
while not (current is None):
ans += str(current)
ans += '\n'
current = current.next
return ans
def _get_node(self,index):
if 0<= index< len(self):
current = self.top
while index>0:
current = current.next
index -=1
return current
def pop(self):
if self.is_empty():
raise StopIteration("Stack is empty")
output = self.top.item
self.top = self.top.next
self.count -=1
return output
def push(self,item):
newNode = Node(item)
newNode.next = self.top
self.top = newNode
self.count +=1
if __name__ == "__main__":
L = LinkedStack()
and in another file, i import the stack from above and try to implement the undo action.
from Stack import LinkedStack
class Editor:
def __init__(self):
self.count = 0
self._list = LinkedList()
self._stack = LinkedStack()
def command(self,userCommand):
userCommand = userCommand.split(' ')
try:
if userCommand[0] == 'insert':
position = int(userCommand[1])
if len(userCommand) ==1:
raise Exception('no num is given')
textInput = input("Enter your text:")
self._stack.push(self.insertText(position,textInput)) #I'm thinking of adding the action into the stack by pushing it.
print(self._list)
pass
except Exception:
print('?')
if userCommand[0] == 'undo': #here if they choose to undo, by right i just pop the last action from the stack
self._stack.pop()
if __name__ == '__main__':
myCommand = Editor()
while True:
command = input('Enter an option:')
if command.lower() == 'quit':
break
else:
myCommand.command(command)
because I'm merely undoing actions, i thought of adding the command actions into a stack. if you take a look at the insert command above, where i added a comment, am i doing it correctly? Because I'm running out of ideas.
By the way, the insertText is a function which is working and I'm not planning to paste it here as it's getting lengthy. LinkedList() is just a linked list class i imported from another file as well.
The 'undo' doesn't seemed to revert the state. For example, if my LinkedList() contains:
1
2
3
4
None
and if i use the insert function to insert another number, 7 at index 1
1
7
2
3
4
None
and if i undo the action, I'm supposed to have:
1
2
3
4
None

How to delete a "node" which is passed to a method in a single linked list using Python

I want to implement 5 ways of deleting a node in a single linked list.
Delete the first element in the list - Easy
Delete the last element in the list - Easy
Delete the element at a position(numeric) - Easy
Delete the element with the given value - Easy
Delete a specific node - Not sure how to do this
I guess the challenge I am facing is how to find the memory address of the node or how to pass the memory address of the node to the method. The following is the code I have come up with. Obviously the " def delete_node(self, node):" does not work. The following is the code I have come up with so far.
from Node import Node
class SingleLinkedList:
"""Constructor. Sets the length of the linkedlist to zero and initializes head reference"""
def __init__(self):
self.head = None
self.length = 0
""" Method to get the length of the list """
def get_list_length(self):
return self.length
""" Method to INSERT a node at the beginning of the list """
def insert_at_beginning(self, data):
new_Node = Node()
new_Node.set_data(data)
if self.length == 0:
self.head = new_Node
else:
new_Node.set_next(self.head)
self.head = new_Node
self.length += 1
""" Method to INSERT a node at the end of the list """
def insert_at_end(self, data):
new_Node = Node()
new_Node.set_data(data)
if self.length == 0:
self.head = new_Node
else:
current = self.head
while current.has_next():
current = current.get_next()
current.set_next(new_Node)
self.length += 1
""" Method to INSERT a node at the given position, i.e. after postion - 1 . Position count start at 0 """
def insert_at_position(self, position, data):
if position > self.length or position < 0:
return None
else:
if position == 0:
self.insert_at_beginning(data)
else:
if position == self.length:
self.insert_at_end(data)
else:
new_Node = Node()
new_Node.set_data(data)
current = self.head
count = 0
while count < (position - 1):
current = current.get_next()
count += 1
new_Node.set_next(current.get_next())
current.set_next(new_Node)
self.length += 1
""" Method to INSERT a new node to the list. Default insertion at the end of the list """
def add(self, data):
self.insert_at_end(data)
""" Method to PRINT the elements of the list """
def print_list(self):
if self.length == 0:
return "Linked List is empty"
else:
current = self.head
while current.has_next():
print str(current.get_data()) + " ---> ",
current = current.get_next()
print str(current.get_data())
""" Method to DELETE the node at the beginning of the list """
def delete_at_beginning(self):
if self.length == 0:
return "List is empty"
else :
self.head = self.head.get_Next()
self.length -= 1
""" Method to DELETE the node at the end of the list """
def delete_at_end(self):
if self.length == 0:
return "List is empty"
else:
current = self.head
previous = None
while current.has_next():
previous = current
current = current.get_next()
previous.set_Next(None)
self.length -= 1
""" Method to DELETE a node at the given position, i.e. after postion - 1 . Position count start at 0 """
def delete_at_position(self, position):
if position > self.length or position < 0:
return "Position does not exist"
else:
if position == 0:
self.delete_at_beginning()
elif position == self.length:
self.delete_at_end()
else:
count = 0
current = self.head
previous = None
while count < position:
previous = current
current = current.get_next()
count += 1
previous.set_next(current.get_next())
self.length -= 1
""" Method to DELETE a node with a given value """
def delete_value(self, value):
if self.length == 0:
print " List is empty "
else:
current = self.head
previous = None
while current.has_next():
if current.get_data() == value:
break
previous = current
current = current.get_next()
if current.get_data() != value:
print "Item " + str(value) + " not in the list"
else:
previous.set_next(current.get_next())
self.length -= 1
def delete_node(self, node):
if self.length == 0:
print "List is empty"
else:
current = self.head
previous = None
found = False
while not found:
if current == node:
found = True
elif current is None:
print "Node not in the list"
return
else:
previous = current
current = current.get_next()
if previous is None:
self.head = current.get_next()
else:
previous.set_next(current.get_next())
self.length -= 1
def main():
l = SingleLinkedList()
print l.get_list_length()
l.add(1)
l.add(2)
l.add(3)
l.print_list()
l.insert_at_beginning(500)
l.insert_at_beginning(600)
l.insert_at_beginning(700)
l.print_list()
l.insert_at_position(3, 99999)
l.print_list()
l.delete_at_position(3)
l.print_list()
l.delete_value(500)
l.print_list()
nd = Node()
nd.set_data(2)
l.delete_node(nd)
l.print_list()
if __name__ == '__main__':
main()
I am following a book on Data Structures written in C++ and translating it to Python. I guess it is easy to pass the memory address in C++, maybe this is not doable using Python?
Any help will be much appreciated.
Thanks
EDIT:
I have another challenge related to this class. I want to be able to find the length/size of the linked list both iteratively and recursively. Finding the length iteratively is straight-forward. How do I find the length recursively? I am able to visualize recursive approach in my head, but unable to code this in Python. Also, this is confusing as self is the first method in the parameter.
def sizeByIteration(self):
current = self.head
counter = 0
while current is not None:
counter += 1
current = current.get_next()
return counter
# def sizeByRecursion(self):
# if self.head is None:
# return 0
# else:
# self.head = self.head.get_next()
# return 1 + self.sizeByRecursion()
You may want to try is instead of ==. is will return True if two variables reference the same object. Whereas == will use a default comparator that compares the value of the objects.
Try this instead:
def delete_node(self, node):
if self.length == 0:
print "List is empty"
else:
current = self.head
previous = None
found = False
while not found:
if current is node:
found = True
elif current is None:
print "Node not in the list"
return
else:
previous = current
current = current.get_next()
if previous is None:
self.head = current.get_next()
else:
previous.set_next(current.get_next())
self.length -= 1
Also as a note: the benefit of python is that you can write very short, concise, and functional code. Take advantage of recursion if you understand the method. If you aren't at that point in university yet, don't worry about this and continue on your merry way.
To call deleted_node() need to find node, that you can only do by traversing the list from head.
So instead of traversing twice, at first traversal itself we can delete node
Also, to find length by recursion
The logic written by you modifies the entire list, instead this will work
def sizeByRecursion(self, node):
if node is None:
return 0
return self.sizeByRecursion(node.get_next()) + 1

Stack data structure in python

I have 2 issues with the code below:
push(o) throws an exception TypeError: can only assign an iterable.
Should I throw an exception if pop() is invoked on an empty stack ?
class Stack(object):
def __init__(self):
self.storage = []
def isEmpty(self):
return len(self.storage) == 0
def push(self,p):
self.storage[:0] = p
def pop(self):
"""issue: throw exception?"""
return None
No need to jump through these loops, See 5.1.1 Using Lists as Stacks
If you insist on having methods isEmpty() and push() you can do:
class stack(list):
def push(self, item):
self.append(item)
def isEmpty(self):
return not self
You are right to use composition instead of inheritance, because inheritance brings methods in that you don't want to expose.
class Stack:
def __init__(self):
self.__storage = []
def isEmpty(self):
return len(self.__storage) == 0
def push(self,p):
self.__storage.append(p)
def pop(self):
return self.__storage.pop()
This way your interface works pretty much like list (same behavior on pop for example), except that you've locked it to ensure nobody messes with the internals.
I won't talk about the list structure as that's already been covered in this question. Instead I'll mention my preferred method for dealing with stacks:
I always use the Queue module. It supports FIFO and LIFO data structures and is thread safe.
See the docs for more info. It doesn't implement a isEmpty() function, it instead raises a Full or Empty exception if a push or pop can't be done.
Stack follows LIFO mechanism.You can create a list and do a normal append() to append the element to list and do pop() to retrieve the element out of the list which you just inserted.
Here is an example for stack class
class Stack(object):
def __init__(self):
self.items = []
def push(self, item):
self.items.append(item)
def pop(self):
return self.items.pop()
def peek(self):
return self.items[-1]
def isEmpty(self):
return len(self.items) == 0
class Stack:
def __init__(self):
self.items=[]
def isEmpty(self):
return self.items==[]
def push(self , item):
self.items.append(item)
def pop(self):
return self.items.pop()
def size(self):
return len(self.items)
def peek(self):
return self.items[-1]
Create a stack
To create a new stack we can simply use Stack()
for example:
s=Stack()
"s" is the name of new stack
isEmpty
By using isEmpty() we can check our stack is empty or not
for example:
we have two stacks name s1=(0,1,4,5,6) and s2=()
if we use print(s1.isEmpty()) it will return False
if we use print(s2.isEmpty()) it will return True
push
By using push operation we can add items to top of the stack
we can add "6" to the stack name "s" using
s.push(6)
pop
we can use pop operation to remove and return the top item of a stack
if there is a stack name "s" with n amount items (n>0)
we can remove it's top most item by using
s.pop()
size
This operation will return how many items are in the stack
if there is a stack name "s" s=(1,2,3,4,5,3)
print(s.size())
will return "6"
peek
This operation returns the top item without removing it
print(s.peek())
"we can print items of the stack using print(s.items)"
class Stack:
def __init__(self):
self.stack = []
def pop(self):
if self.is_empty():
return None
else:
return self.stack.pop()
def push(self, d):
return self.stack.append(d)
def peek(self):
if self.is_empty():
return None
else:
return self.stack[-1]
def size(self):
return len(self.stack)
def is_empty(self):
return self.size() == 0
class stack:
def __init__(self,n):##constructor
self.no = n ##size of stack
self.Stack = [] ##list for store stack items
self.top = -1
def push(self):##push method
if self.top == self.no - 1 :##check full condition
print("Stack Overflow.....")
else:
n = int(input("enter an element :: "))
self.Stack.append(n) ## in list add stack items use of append method
self.top += 1##increment top by 1
def pop(self):## pop method
if self.top == -1: #check empty condition
print("Stack Underflow....")
else:
self.Stack.pop()## delete item from top of stack using pop method
self.top -= 1 ## decrement top by 1
def peep(self): ##peep method
print(self.top,"\t",self.Stack[-1]) ##display top item
def disp (self): #display method
if self.top == -1:# check empty condition
print("Stack Underflow....")
else:
print("TOP \tELEMENT")
for i in range(self.top,-1,-1): ## print items and top
print(i," \t",self.Stack[i])
n = int(input("Enter Size :: ")) # size of stack
stk = stack(n) ## object and pass n as size
while(True): ## loop for choice as a switch case
print(" 1: PUSH ")
print(" 2: POP ")
print(" 3: PEEP ")
print(" 4: PRINT ")
print(" 5: EXIT ")
option = int(input("enter your choice :: "))
if option == 1:
stk.push()
elif option == 2:
stk.pop()
elif option == 3:
stk.peep()
elif option == 4:
stk.disp()
elif option == 5:
print("you are exit!!!!!")
break
else:
print("Incorrect option")

Categories

Resources