Next function on iterator stalls program - python

The program below stalls at line:
m = MapH()
This is related with the function:
def next(self):
If redefined as (should be only two underscores):
def __next__(self):
Then, got error message:
instance has no next() method
When hitting the line:
for e in m:
The full code is below:
class MapEntryH:
def __init__(self, key, value):
self.key = key
self.value = value
class MapIteratorH:
def __init__(self,entryList):
self._myEntryList = entryList
self._currItem = 0
def __iter__(self):
return self
def __next__(self):
if self._currItem < len(self._myEntryList):
item = self._myEntryList[self._currItem]
self._currItem += 1
return item
else:
StopIteration
class MapH:
def __init__(self):
self._entryList = list()
def __len__(self):
return len(self._entryList)
def _findPosition(self,key):
for i in range(len(self)):
if self._entryList[i].key == key:
return i
return None
def __contains__(self,key):
ndx = self._findPosition(key)
return ndx is not None
def add(self,key,value):
ndx = self._findPosition(key)
if ndx is not None:
self._entryList[ndx].value = value
return False
else:
entry = MapEntryH(key,value)
self._entryList.append(entry)
return True
def valueOf(self, key):
ndx = self._findPosition(key)
assert ndx is not None, "Invalid map key"
return self._entryList[ndx].value
def remove(self,key):
ndx =self._findPosition(key)
assert ndx is not None,"Invalid map key"
self._entryList.pop(ndx)
def __iter__(self):
return MapIteratorH(self._entryList)
def test_Map():
m = MapH()
m.add(1,"arg")
m.add(2,"eeu")
m.add(3,"ale")
m.add(4,"sue")
m.add(5,"bra")
temp = m.remove(5)
m.add(5,"chl")
m.add(5,"bol")
temp = m.valueOf(5)
temp = m._findPosition(4)
for e in m:
print(e)
me = MapEntryH(1,"arg")
test_Map()
How do I support iteration like:
for e in m:
print(e)
Or containment like:
me = MapEntryH(1,"arg")
if me in m:
print me.value + " is on the map"

Related

Is there a way to have a object type of your choice (i.e. LinkedEdge) hash as part of a 'union.set()' processing?

I have the following code and it works until it gets to the 'union.set()' part. It says, "unhashable type: 'LinkedEdge' " . I am not sure why this is the case since I have looked at other sources on the web and in reference books to know that the 'g.addVertex()' method and the 'g.addEdge()' method as well as the arguments being passed should lead correctly to an output like this:
5 Vertices: A C B E D
5 Edges: A>B:3 A>C:2 B>D:1 C>D:1 D>E:2
class LinkedEdge(object):
def __init__(self, fromVertex, toVertex, weight = None):
self._vertex1 = fromVertex
self._vertex2 = toVertex
self._weight = weight
self._mark = False
def clearMark(self):
self._mark = False
def __eq__(self, other):
if self is other: return True
if type(self) != type(other):
return False
return self._vertex1 == other._vertex1 and self._vertex2 == other._vertex2
def getOtherVertex(self, thisVertex):
if thisVertex == None or thisVertex == self._vertex2:
return self._vertex1
else:
return self._vertex2
def getToVertex(self):
return self._vertex2
def getWeight(self):
return self._weight
def isMarked(self):
return self._mark
def setMark(self):
self._mark = True
def setWeight(self, weight):
self._weight = weight
def __str__(self):
return str(self._vertex1) + ">" + str(self._vertex2) + ":" + str(self._weight)
class LinkedVertex(object):
def __init__(self, label):
self._label = label
self._edgeList = []
self._mark = False
def clearMark(self):
self._mark = False;
def getLabel(self):
return self._label
def isMarked(self):
return self._mark
def setLabel(self, label, g):
g._vertices.pop(self._label, None)
g._vertices[label] = self
self._label = label
def setMark(self):
self._mark = True
def __str__(self):
return str(self._label)
def addEdgeTo(self, toVertex, weight):
edge = LinkedEdge(self, toVertex, weight)
self._edgeList.append(edge)
def getEdgeTo(self, toVertex):
edge = LinkedEdge(self, toVertex)
try:
return self._edgeList[self._edgeList.index(edge)]
except:
return None
def incidentEdges(self):
return iter(self._edgeList)
def neighboringVertices(self):
vertices = []
for edge in self._edgeList:
vertices.append(edge.getOtherVertex(self))
return iter(vertices)
def removeEdgeTo(self, toVertex):
edge = LinkedEdge(self, toVertex)
if edge in self._edgeList:
self._edgeList.remove(edge)
return True
else:
return False
class LinkedDirectedGraph(object):
def __init__(self, collection = None):
self._vertexCount = 0
self._edgeCount = 0
self._vertices = {}
if collection != None:
for label in collection:
self.addVertex(label)
# Methods for clearing, marks, sizes, string rep
def clear(self):
self._vertexCount = 0
self._edgeCount = 0
self._vertices = {}
def clearEdgeMarks(self):
for edge in self.edges():
edge.clearMark()
def clearVertexMarks(self):
for vertex in self.vertices():
vertex.clearMark()
def isEmpty(self):
return self._vertexCount == 0;
def sizeEdges(self):
return self._edgeCount
def sizeVertices(self):
return self._vertexCount
def __str__(self):
result = str(self.sizeVertices()) + " Vertices: "
for vertex in self._vertices:
result += " " + str(vertex)
result += "\n";
result += str(self.sizeEdges()) + " Edges: "
for edge in self.edges():
result += " " + str(edge)
return result
def addVertex(self, label):
self._vertices[label] = LinkedVertex(label)
self._vertexCount += 1
def containsVertex (self, label):
return label in self._vertices
def getVertex(self, label):
return self._vertices[label]
def removeVertex(self, label):
removedVertex = self._vertices.pop(label, None)
if removedVertex is None:
return False
# Examine all vertices
for vertex in self.vertices():
if vertex.removeEdgeTo(removedVertex):
self._edgeCount -= 1
self._vertexCount -= 1
return True
def addEdge(self, fromLabel, toLabel, weight):
fromVertex = self.getVertex(fromLabel)
toVertex = self.getVertex(toLabel)
fromVertex.addEdgeTo(toVertex, weight)
self._edgeCount += 1
def containsEdge(self, fromLabel, toLabel):
return self.getEdge(fromLabel, toLabel) != None
def getEdge(self, fromLabel, toLabel):
fromVertex = self._vertices[fromLabel]
toVertex = self._vertices[toLabel]
return fromVertex.getEdgeTo(toVertex)
def removeEdge (self, fromLabel, toLabel):
fromVertex = self.getVertex(fromLabel)
toVertex = self.getVertex(toLabel)
edgeRemovedFlg = fromVertex.removeEdgeTo(toVertex)
if edgeRemovedFlg:
self._edgeCount -= 1
return edgeRemovedFlg
# Iterators
def edges(self):
result = set()
for vertex in self.vertices():
edges = vertex.incidentEdges()
result = result.union(set(edges))
return iter(result)
def vertices(self):
return iter(self._vertices.values())
def incidentEdges(self, label):
return self._vertices[label].incidentEdges()
def neighboringVertices(self, label):
return self._vertices[label].neighboringVertices
g = LinkedDirectedGraph()
# Insert vertices
g.addVertex("John")
g.addVertex("Sam")
g.addVertex("Megan")
g.addVertex("Jennifer")
g.addVertex("Rick")
# Insert weighted edges
g.addEdge("John", "Sam", 3)
g.addEdge("John", "Megan", 2)
g.addEdge("Sam", "Jennifer", 1)
g.addEdge("Megan", "Jennifer", 1)
g.addEdge("Jennifer", "Rick", 2)
print(g)
If you override __eq__, then Python intentionally makes your class unhashable, since there is no longer a guarantee that the default hashing algorithm (based on the object's location in memory) is compatible with your __eq__ algorithm. "Compatible" here just means that equal objects must have equal hashes. By default, nothing is equal, so when you make some things equal using an __eq__ method, you impose a requirement on what a proper hash function must do.
If you want a custom class with a custom __eq__ method to be hashable, you must implement a __hash__ method yourself.
It could be as simple as being based on the hash of the corresponding tuple:
def __hash__(self):
return hash((type(self), self._vertex1, self._vertex2))
The Python docs explain this here.

Finding Method for Binary Tree doesn't return anything

I have a Binary Tree and want to search for elements in it.
But for some reason i'm not getting any output and no error. Tried debugging as well but the code is always being executed until the end.
def find(self, i):
if self.__head is None:
return -1
else:
return self.__find(self.__head, i)
def __find(self, element, i):
if element is not None:
if i == element.value():
return 1
elif i < element.value():
self.__find(element.getLeft(), i)
else:
self.__find(element.getRight(), i)
else:
return -1
The code for the Elements is the following:
class BElement:
def __init__(self, i, v):
self.__id = i
self.__value = v
self.__left = None
self.__right = None
def id(self):
return self.__id
def value(self):
return self.__value
def getLeft(self):
return self.__left
def setLeft(self, l):
self.__left = l
def getRight(self):
return self.__right
def setRight(self, r):
self.__right = r
def __str__(self):
s = "{"
if self.__left is not None:
s = s + str(self.__left)
s = s + str(self.__id) + ":" + str(self.__value)
if self.__right is not None:
s = s + str(self.__right)
s = s + "}"
return s
remove the brackets() after value,left and right they are not methods.

Python: Attribute error Nonetype object has no attribute 'nxt'

I am having trouble sorting this singly linked list. The goal is to sort a polynomial by its exponent in descending order. However I keep getting attribute error: Nonetype has no attribute 'nxt' and I can't understand why. Here is my code below
NodeModule.py
!/usr/bin/python
import sys
sys.setrecursionlimit(4500)
"""A model containing Node class"""
class Node(object):
"""A single node in a data structure"""
def __init__(self, _coefficient, _exponent):
self._coefficient=_coefficient
self._exponent=_exponent
self.nxt=None
#property
def coefficient(self):
return self._coefficient
#coefficient.setter
def coefficient(self, c):
self._coefficient=c
#coefficient.deleter
def coefficient(self):
del self.coefficient
#property
def exponent(self):
return self._exponent
#exponent.setter
def exponent(self, e):
self._exponent=e
#exponent.deleter
def exponent(self):
del self._exponent
#property
def nxt(self):
return self._next
#nxt.setter
def nxt(self, n):
self._next=n
#nxt.deleter
def nxt(self):
del self._next
def __eq__(self, other):
if self._exponent==other._exponent:
return True
else:
return False
def __It__(self, other):
if self._exponent<other._exponent:
return True
else:
return False
def __str(self):
if self._coefficient>=0:
sign="+"
else:
sign=""
return sign +str(self._coefficient) + "X^" +str(self._exponent)
ListModule.py
!/usr/bin/python
from NodeModule import Node
class List(Node):
"""Linked list with pre-defined Node class"""
def __init__(self):
self.head=None
self.count=0
def isEmpty(self):
return self.count==0
def getSize(self):
return self.count
def setNode(self, a=5, b=2):
n=Node(a, b)
return n
def insert(self, index, n):
if index<0 or index > self.count:
return False
if index==0:
n.next=self.head
self.head=n
self.count+=1
return True
walker=self.head
for i in range(index-1):
walker=walker.nxt
n.nxt=walker.nxt
walker.next=n
self.count+=1
return True
def delete(self, index):
if index < 0 or index > self.count:
return False
if index==0:
self.head=self.head.nxt
self.count-=1
return True
walker=self.head
for i in range(index-1):
walker=walker.nxt
walker.nxt=walker.nxt.nxt
self.count-=1
return True
def sort(self):
temp1=self.head.exponent
walker=self.head
j=0
while j < self.count:
for i in range(self.count):
walker=walker.nxt
if i==0:
if walker.nxt.exponent > temp1:
self.insert(0, walker.nxt)
self.delete(walker.nxt)
return True
while walker.nxt is not None and walker.nxt.nxt is not None:
if walker.nxt.exponent < walker.nxt.nxt.exponent:
self.insert(self.getsize(), walker.nxt.nxt)
self.delete(walker.nxt)
return True
return False
j+=1
def str(self):
if self.isEmpty():
return "\nEnd of Polynomial"
walker=self.head
output=[]
while walker is not None:
output.append(str(walker))
walker=walker._next
return " + " .join(output)
main.py
!/usr/bin/python
from NodeModule import Node
from ListModule import List
def readPoly(message):
l=List()
n=input(message)
for i in range(n):
c=input("Enter the coefficient of term %d " % i)
e=input("Enter the exponent of term %d " % i)
l.insert(0, Node(c,e))
return l
def main():
l=readPoly("Enter the number of terms of the polynomial: ")
print l
l.sort()
print l
l.delete(0)
print (l)
if name=='main':
main()
It appears self.head=None, walker=self.head and walker=walker.nxt within the second code block. This means by inference you're trying to get the .nxt property of None (a NoneType), which you set as self.head at the start.

How does a node with return self work?(Python)

So this is the node part of a singly linked list. I am not supposed to change the way it has been coded, but I dont know how this type of structure would work. Self.link cannot event be accessed to point towards another part of the list. Does anyone know how to work with such a Node class?
class Node:
def __init__(self, inval=None):
self.val = inval
if inval==None:
self.link = self
print (self)
def __str__(self):
if self.val == None:
return ''
else:
return str(self.val)
def __repr__(self):
return str(self)
Here is another implementation of the linked list, which has a slightly different styled node.
class LinkedList:
lock = 0
if lock == 0:
tempdata = None
def __init__(self, *args):
self.head = Node() # Node at the head of the list
self.current = None # Node currently pointed to by the iterator
self.count = 0
def insert(self, value):
NewNode =Node(value)
NewNode.link = self.head
self.head = NewNode
self.count += 1
def __iter__(self):
self.current = self.head
return self
def __next__(self):
self.current = LinkedList.tempdata
if LinkedList.lock == 0:
self.current = self.head
LinkedList.lock += 1
else:
pass
if self.current.value == None:
LinkedList.lock = 0
raise StopIteration
previous = self.current
self.current = self.current.link
LinkedList.tempdata = self.current
return previous
def __str__(self):
result = ''
self.current = self.head
while self.current.value is not None:
if self.current.link.value is None:
result += str(self.current.value)
else:
result += str(self.current.value) + ' -> '
self.current = self.current.link
return result
def search(self, value):
found = 0
temp = None
out= False
while found == 0:
try:
temp = LinkedList.__next__(self)
if temp.value == value:
found += 1
out = temp
except StopIteration:
pass
return out
def delete(self, value):
print ("hwta")
found = 0
temp = None
head = self.head
if head.value == value:
print ("Head")
if head.link.value != None:
self.head = head.link
else:
self.head = Node()
else:
while found == 0:
try:
temp = LinkedList.__next__(self)
if temp.link.value == value:
if temp.link.link.value == None:
temp.link = Node()
break
else:
temp.link = temp.link.link
print ("tails")
break
except StopIteration:
pass
def __repr__(self):
return str(self)
#a = Node()
#print(a) # 3
#b = Node("Hullo")
#print(b) # 'Hullo'
#lst = LinkedList()
#lst.insert(2)
#lst.insert(3)
#lst.insert(5)
#lst.insert(6)
#lst.insert(7)
#lst.insert(6)
#print(lst) # 5 -> 3 -> 2
#c = lst.search(2)
#print(c) # 3
#print(c.link) # 5
#lst.insert(2)
#print(lst.head.link.link) # 3
lst.delete(6)
print (lst)
#print(next(lst)) # should print 5, 3, 2 on separate lines
#lst.delete(2)
#print(lst) # 5 -> 3
#print(len(lst)) # 2
#for u in lst:
# print(u)
Nothing in the Node implementation that would prevent you from using it in a List class. Just pretend that the final three lines of Node.__init__() don't exist.
Here is one way to use the professor's Node in your List.
class Node:
def __init__(self, inval=None):
self.val = inval
if inval==None:
self.link = self
print (self)
def __str__(self):
if self.val == None:
return ''
else:
return str(self.val)
def __repr__(self):
return str(self)
class List:
def __init__(self):
self.head = None
def prepend(self, val):
head = Node(val)
head.link = self.head
self.head = head
def append(self, val):
if self.head is None:
self.prepend(val)
else:
p = self.head
while p.link is not None:
p = p.link
p.link = Node(val)
p.link.link = None
def __str__(self):
result = '<'
p = self.head
while p is not None:
result += str(p) + ', '
p = p.link
result += '>'
return result
l = List()
l.append(3)
l.prepend(2)
l.append(4)
l.prepend(1)
l.append(5)
print(str(l))
And here is the result:
<1, 2, 3, 4, 5, >

Python binary search tree height function wont work

I've been trying the recursive approach but been stuck for too long. I cant tell if it's my BST code that's wrong or my recursion.
Regardless of how many elements I put in my tree I still get the value 2 from my height function.
class Treenode:
def __init__(self, value = None, rchild = None, lchild = None):
self.value = value
self.rchild = rchild
self.lchild = lchild
class bin_tree:
def __init__(self):
self.root = None
def put(self, x):
if self.root is None:
self.root = Treenode(x)
return True
if self.exists(x) == True:
return False
p = self.root
while True:
if x < p.value:
if p.lchild is None:
p.lchild = Treenode(x)
return True
else:
p = p.lchild
elif x > p.value:
if p.rchild is None:
p.rchild = Treenode(x)
return True
else:
p = p.rchild
return
def exists(self, x):
p = self.root
while True and p != None:
if p.value == x:
return True
elif p.value > x and p.lchild != None:
p = p.lchild
elif p.value < x and p.rchild != None:
p = p.rchild
else:
return False
def isempty(self):
return self.root == None
def height(self):
def gh(enrot):
if enrot == None:
return 0
else:
return 1 + max(gh(enrot.lchild), gh(enrot.rchild))
return gh(self.root)
Example code:
from Bintree import *
p = bin_tree()
x = input()
for word in x.split():
p.put(word)
a = input()
if p.exists(a) is True:
print('Exists!')
else:
print('Does not exist!')
print(p.isempty())
print(p.height())
The height method is fine. In your put method, you stop without actually adding the element, so the height doesn't actually grow beyond 2:
def put(self, x):
...
while True:
if x < p.value:
...
elif x > p.value:
if p.rchild is None:
...
else:
p = p.rchild
return
# ^^^^^^ This shouldn't be here.

Categories