I'm working on a dijkstra and I get this error:
TypeError: unorderable types: Vertex() < Vertex()
The whole error log is:
Traceback (most recent call last):
File "C:/Users/Dimitar/PycharmProjects/Dijkstra/Dijkstra.py", line 165, in <module>
dijkstra(g, g.get_vertex('a'))
File "C:/Users/Dimitar/PycharmProjects/Dijkstra/Dijkstra.py", line 101, in dijkstra
heapq.heapify(unvisited_queue)
TypeError: unorderable types: Vertex() < Vertex()
Here is my code :
import sys
class Vertex:
def __init__(self, node):
self.id = node
self.adjacent = {}
# Set distance to infinity for all nodes
self.distance = sys.maxsize
# Mark all nodes unvisited
self.visited = False
# Predecessor
self.previous = None
def add_neighbor(self, neighbor, weight=0):
self.adjacent[neighbor] = weight
def get_connections(self):
return self.adjacent.keys()
def get_id(self):
return self.id
def get_weight(self, neighbor):
return self.adjacent[neighbor]
def set_distance(self, dist):
self.distance = dist
def get_distance(self):
return self.distance
def set_previous(self, prev):
self.previous = prev
def set_visited(self):
self.visited = True
def __str__(self):
return str(self.id) + ' adjacent: ' + str([x.id for x in self.adjacent])
class Graph:
def __init__(self):
self.vert_dict = {}
self.num_vertices = 0
def __iter__(self):
return iter(self.vert_dict.values())
def add_vertex(self, node):
self.num_vertices = self.num_vertices + 1
new_vertex = Vertex(node)
self.vert_dict[node] = new_vertex
return new_vertex
def get_vertex(self, n):
if n in self.vert_dict:
return self.vert_dict[n]
else:
return None
def add_edge(self, frm, to, cost=0):
if frm not in self.vert_dict:
self.add_vertex(frm)
if to not in self.vert_dict:
self.add_vertex(to)
self.vert_dict[frm].add_neighbor(self.vert_dict[to], cost)
self.vert_dict[to].add_neighbor(self.vert_dict[frm], cost)
def get_vertices(self):
return self.vert_dict.keys()
def set_previous(self, current):
self.previous = current
def get_previous(self, current):
return self.previous
def shortest(v, path):
''' make shortest path from v.previous'''
if v.previous:
path.append(v.previous.get_id())
shortest(v.previous, path)
return
import heapq
# noinspection PyArgumentList
def dijkstra(aGraph, start):
print('''Dijkstra's shortest path''')
# Set the distance for the start node to zero
start.set_distance(0)
# Put tuple pair into the priority queue
unvisited_queue = [(v.get_distance(), v) for v in aGraph]
heapq.heapify(unvisited_queue)
while len(unvisited_queue):
# Pops a vertex with the smallest distance
uv = heapq.heappop(unvisited_queue)
current = uv[1]
current.set_visited()
for next in current.adjacent:
# if visited, skip
if next.visited:
continue
new_dist = current.get_distance() + current.get_weight(next)
if new_dist < next.get_distance():
next.set_distance(new_dist)
next.set_previous(current)
print
('updated : current = %s next = %s new_dist = %s' \
% (current.get_id(), next.get_id(), next.get_distance()))
else:
print
('not updated : current = %s next = %s new_dist = %s' \
% (current.get_id(), next.get_id(), next.get_distance()))
# Rebuild heap
# 1. Pop every item
while len(unvisited_queue):
heapq.heappop(unvisited_queue)
# 2. Put all vertices not visited into the queue
unvisited_queue = [(v.get_distance(), v) for v in aGraph if not v.visited]
heapq.heapify(unvisited_queue)
if __name__ == '__main__':
g = Graph()
g.add_vertex('a')
g.add_vertex('b')
g.add_vertex('c')
g.add_vertex('d')
g.add_vertex('e')
g.add_vertex('f')
g.add_edge('a', 'b', 7)
g.add_edge('a', 'c', 9)
g.add_edge('a', 'f', 14)
g.add_edge('b', 'c', 10)
g.add_edge('b', 'd', 15)
g.add_edge('c', 'd', 11)
g.add_edge('c', 'f', 2)
g.add_edge('d', 'e', 6)
g.add_edge('e', 'f', 9)
print
('Graph data:')
for v in g:
for w in v.get_connections():
vid = v.get_id()
wid = w.get_id()
print
('( %s , %s, %3d)' % ( vid, wid, v.get_weight(w)))
dijkstra(g, g.get_vertex('a'))
target = g.get_vertex('e')
path = [target.get_id()]
shortest(target, path)
print('The shortest path : %s' % (path[::-1]))
Can some one explain me why I get this kind of error. I'm a self learner and some help will be really appreciated.
The line of code that causes the error is :
heapq.heapify(unvisited_queue)
Thanks in advance to everyone who comment on the topic.
Best,
Dimitar
A custom type does not implicitly define an ordering between its instances:
>>> v1 = Vertex(1)
>>> v2 = Vertex(2)
>>> v1 < v2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: Vertex() < Vertex()
You need to tell python how to compare your vertices. You need to implement rich comparison methods to do so. Since heapify requires <, you must at least implement __lt__.
You can also have a look at the #total_ordering decorator to avoid implementing all of them.
Something along the lines of:
from functools import total_ordering
#total_ordering
class Vertex:
# Your current class code
def __eq__(self, other):
if isinstance(other, self.__class__):
return self.distance == other.distance
return NotImplemented
def __lt__(self, other):
if isinstance(other, self.__class__):
return self.distance < other.distance
return NotImplemented
And if you need to use that class as a dictionary key, you’ll need to add the __hash__ method. Probably like so:
def __hash__(self):
return id(self)
Related
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.
Here is my code for Dijkstra's Algorithm.
I have declared a "Vertex" class and a "Graph" class.
I am using heapq module and heapifying the list "unvisitedQueue" of tuples. But even then an error shows up saying " TypeError: '<' not supported between instances of 'Vertex' and 'Vertex' " even when "v.getDistance()" returns either 0 or float('inf').
import heapq
class Vertex:
def __init__(self, node):
self.id = node
self.adjacent = {}
self.previous = None
self.distance = float('inf')
def addNeighbor(self, neighbor, weight = 0):
self.adjacent[neighbor] = weight
def getConnections(self):
return self.adjacent.keys()
def getVertex_ID(self):
return self.id
def getWeight(self, neighbor):
return self.adjacent[neighbor]
def setDistance(self, dist):
self.distance = dist
def getDistance(self):
return self.distance
def setPrevious(self, prev):
self.previous = prev
def __str__(self):
return str(self.id) + "adjacent : " + str([x.id for x in self.adjacent])
class Graph:
def __init__(self):
self.vertDictionary = {}
self.numVertices = 0
def __iter__(self):
return iter(self.vertDictionary.values())
def addVertex(self, node):
self.numVertices += 1
newVertex = Vertex(node)
self.vertDictionary[node] = newVertex
return newVertex
def getVertex(self, node):
if node in self.vertDictionary:
return self.vertDictionary[node]
else:
return None
def addEdge(self, frm, to, cost = 0):
if frm not in self.vertDictionary:
self.addVertex(frm)
if to not in self.vertDictionary:
self.addVertex(to)
self.vertDictionary[frm].addNeighbor(self.vertDictionary[to], cost)
self.vertDictionary[to].addNeighbor(self.vertDictionary[frm], cost)
def getVertices(self):
return self.vertDictionary.keys()
def setPrevious(self, current):
self.previous = current
def getPrevious(self):
return self.previous
def getEdges(self):
edges = []
for v in G:
for w in v.getConnections():
v_id = v.getVertex_ID()
w_id = w.getVertex_ID()
edges.append((v_id, w_id, v.getWeight(w)))
return edges
def Dijkstra(G, s):
source = G.getVertex(s)
source.setDistance(0)
visited = {}
unvisitedQueue = [(v.getDistance(), v) for v in G]
heapq.heapify(unvisitedQueue)
while len(unvisitedQueue):
uv = heapq.heappop(unvisitedQueue)
currVert = uv[1]
visited[currVert] = True
for nbr in currVert.getConnections():
if currVert.getDistance() + currVert.getWeight(nbr) < nbr.getDistance():
nbr.setDistance(currVert.getDistance() + currVert.getWeight(nbr))
print("Updated: Current = %s Neighbour = %s New Distance = %s" %(currVert.getVertex_ID(), nbr.getVertex_ID(), nbr.getDistance()))
else:
print("Not Updated: Current = %s Neighbour = %s Distance = %s" %(currVert.getVertex_ID(), nbr.getVertex_ID(), nbr.getDistance()))
while len(unvisitedQueue):
heapq.heappop(unvisitedQueue)
unvisitedQueue = [(v.getDistance(), v) for v in G if v not in visited]
heapq.heapify(unvisitedQueue)
for v in G:
print(source.getVertex_ID(), "to", v.getVertex_ID(), "-->", v.getDistance())
ERROR -->
Traceback (most recent call last):
File "d:\Python\Final 450\Graph\Dijkstra's_Algo.py", line 124, in <module>
print(Dijkstra(G, "a"))
File "d:\Python\Final 450\Graph\Dijkstra's_Algo.py", line 86, in Dijkstra
heapq.heapify(unvisitedQueue)
TypeError: '<' not supported between instances of 'Vertex' and 'Vertex'
The error is happening because tuples are compared lexicographically. If two distances are the same, the comparison moves on to the Vertex objects themselves.
Two solutions readily come to mind. The first is simply to add a unique index to the tuple before the Vertex but after the distance. This is easy, and would work even if you didn't have access to the Vertex class:
unvisitedQueue = [(v.getDistance(), i, v) for i, v in enumerate(G) if v not in visited]
The second option is to modify Vertex to have a __lt__ magic method:
def __lt__(self, other):
return self.getDistance() < other.getDistance()
This is nice because you can heapify more directly now:
unvisitedQueue = [v for v in G if v not in visited]
I have been trying to use Dijkstra's algorithm with an implementation of a priority queue and a distance table, in Python.
This is the priority queue implementation:
from heapq import heapify, heappush, heappop
class priority_dict(dict):
def __init__(self, *args, **kwargs):
super(priority_dict, self).__init__(*args, **kwargs)
self._rebuild_heap()
def _rebuild_heap(self):
self._heap = [(v, k) for k, v in self.items()]
heapify(self._heap)
def smallest(self):
heap = self._heap
v, k = heap[0]
while k not in self or self[k] != v:
heappop(heap)
v, k = heap[0]
return k
def pop_smallest(self):
heap = self._heap
v, k = heappop(heap)
while k not in self or self[k] != v:
v, k = heappop(heap)
del self[k]
return k
def __setitem__(self, key, val):
super(priority_dict, self).__setitem__(key, val)
if len(self._heap) < 2 * len(self):
heappush(self._heap, (val, key))
else:
self._rebuild_heap()
def setdefault(self, key, val):
if key not in self:
self[key] = val
return val
return self[key]
def update(self, *args, **kwargs):
super(priority_dict, self).update(*args, **kwargs)
self._rebuild_heap()
def sorted_iter(self):
while self:
yield self.pop_smallest()
And this is the Dijkstra implementation:
import priority_dict
from graph import *
def build_distance_table(graph, source):
distance_table = {}
for i in range(graph.numVertices):
distance_table[i] = (None, None)
distance_table[source] = (0, source)
priority_queue = priority_dict.priority_dict()
priority_queue[source] = 0
while len(priority_queue.keys()) > 0:
current_vertex = priority_queue.pop_smallest()
current_distance = distance_table[current_vertex][0]
for neighbor in graph.get_adjacent_vertices(current_vertex):
distance = current_distance + g.get_edge_weight(current_vertex, neighbor)
neighbor_distance = distance_table[neighbor][0]
if neighbor_distance is None or neighbor_distance > distance:
distance_table[neighbor] = (distance, current_vertex)
priority_queue = distance
return distance_table
def shortest_path(graph, source, destination):
distance_table = build_distance_table(graph, source)
path = [destination]
previous_vertex = distance_table[destination][1]
while previous_vertex and previous_vertex is not source:
path = [previous_vertex] + path
previous_vertex = distance_table[previous_vertex][1]
if previous_vertex is None:
print("There is no path from %d to %d" % (source, destination))
else:
path: [source] + path
print("Shortest path is: ", path)
This is the result:
Traceback (most recent call last):
File "dijkstra.py", line 76, in <module>
shortest_path(g, 0, 6)
File "dijkstra.py", line 46, in shortest_path
distance_table = build_distance_table(graph, source)
File "dijkstra.py", line 23, in build_distance_table
while len(priority_queue.keys()) > 0:
AttributeError: 'numpy.float64' object has no attribute 'keys'
I am using Python 3.7. I have searched online and though it had to do with the Python version. Can't figure why it doesn't see the attribute. Could you please tell me what am I missing?
priority_queue = distance
Should have been:
priority_queue[neighbor] = distance
Solved it, thank you.
I have trouble using recursion with linked lists.
I want to be able to add another node to an ordered linked list.
I have this class:
class Link:
def __init__(self,value,next=None):
self.value = value
self.next = next
Below is the recursive function, that so far doesn't do much except identifying base cases
Note: it's not a method in Link, it's a separate function:
def add(ll, v):
if ll == None:
return Link(v)
else:
ll.next = add(ll.next,v)
return ll
Example: I have this linked list A:
1->3->8->12->None
I call add(A, 10) which should add 10 in the right order.
1->3->8->10->12->None
How should I modify my code to make that work?
You need an extra base case, to stop the recursion when you find a value that is not less than the one you want to insert in order:
elif v <= ll.value:
return Link(v, ll)
So the complete code could be:
class Link:
def __init__(self,value,next=None):
self.value = value
self.next = next
def values(self):
yield self.value
if self.next:
yield from self.next.values()
def add(ll, v):
if ll is None:
return Link(v)
elif v <= ll.value:
return Link(v, ll)
else:
ll.next = add(ll.next, v)
return ll
# example list
A = Link(1, Link(3, Link(8, Link(12))))
# add 10 to it:
A = add(A, 10)
# print list
print(list(A.values()))
Recursion is a functional heritage and so using it with functional style yields the best results. We start with the smallest bits first -
# linked_list.py
empty = None
class node:
def __init__(self, value, next = empty):
self.value = value
self.next = next
def to_str(ll = empty):
if not ll:
return "None"
else:
return f"{ll.value}->{to_str(ll.next)}"
# main.py
from linked_list import node, to_str
t = node(1, node(3, node(8, node(12))))
print(to_str(t))
# 1->3->8->12->None
Now we implement add -
# linked_list.py
empty = # ...
class node: # ...
def to_str(ll = empty): # ...
def add(ll = empty, v = 0):
if not ll:
return node(v)
elif ll.value >= v:
return node(v, ll)
else:
return node(ll.value, add(ll.next, v))
# main.py
from linked_list import node, to_str, add
t = node(1, node(3, node(8, node(12))))
print(to_str(t))
# 1->3->8->12->None
t2 = add(t, 10)
print(to_str(t2))
# 1->3->8->10->12->None
Now we see how to make bigger bits by combining smaller bits. We could make a linked_list class to bundle it up -
# linked_list.py
empty = # ...
class node: # ...
def to_str(ll = empty): # ...
def add(ll = empty, v = 0): # ...
class linked_list:
def __init__(self, root = empty):
self.root = root
def __str__(self):
return to_str(self.root)
def add(self, v):
return linked_list(add(self.root, v))
Now we can use linked_list in object-oriented style but still get the persistent benefits of functional style -
#main.py
from linked_list import linked_list
t = linked_list().add(1).add(3).add(8).add(12)
print(t)
# 1->3->8->12->None
print(t.add(10))
# 1->3->8->10->12->None
print(t)
# 1->3->8->12->None
Maybe we could expand our linked_list module by defining from_list and to_list -
# linked_list.py
empty = # ...
class node: # ...
def to_str(ll = empty): # ...
def add(ll = empty, v = 0): # ...
def from_list(l = []):
if not l:
return empty
else:
return node(l[0], from_list(l[1:]))
def to_list(ll = empty):
if not ll:
return []
else:
return [ ll.value ] + to_list(ll.next)
class linked_list:
def __init__ # ...
def __str__ # ...
def add # ...
def from_list(l):
return linked_list(from_list(l))
def to_list(self):
return to_list(self.root)
# main.py
from linked_list import linked_list
t = linked_list.from_list([ 1, 3, 8, 12 ])
print(t)
# 1->3->8->12->None
print(t.add(10))
# 1->3->8->10->12->None
print(t.add(11).to_list())
# [1, 3, 8, 11, 12]
I've created a Set class that has the set types, ListSet and DictSet which are represented by a list and dictionary respectively. Both sets need to be iterable which I've created a SetIterator class to do so, however when I try testing DictSet, I get the following errors:
Traceback (most recent call last):
File "Set.py", line 118, in <module>
inter = e.intersection(t)
File "Set.py", line 22, in intersection
if element in other:
File "Set.py", line 8, in __next__
current_element = self.elements[self.index]
KeyError: 0
It seems as though there's an error within my SetIterator class, and I've tried rewriting the line I think is causing the error, but it hasn't fixed anything
def new(obj, *args, **kwargs):
return type(obj)(*args, **kwargs)
class SetIterator:
def __init__(self, s):
self.elements = s.members()
self.index = 0
def __next__(self):
try:
current_element = self.elements[self.index]
except IndexError:
raise StopIteration()
self.index += 1
return current_element
class Set:
def __iter__(self):
return SetIterator(self)
def intersection(self, other):
new_set = new(self) # to hold intersected set
for element in self:
if element in other:
new_set.add(element)
return new_set
def union(self, other):
new_set = new(self) # to hold unionized set
for element in self:
new_set.add(element)
for element in other:
if element not in new_set:
new_set.add(element)
return sorted(new_set)
def difference(self, other):
new_set = new(self) #to hold set difference
for element in self:
if element not in other:
new_set.add(element)
return new_set
def equals(self, other):
new_set = new(self)
other_set = new(self)
for element in self:
if element in other:
new_set.add(element)
for element in other:
if element in self:
other_set.add(element)
if new_set == other_set:
return True
else:
return False
def notEmpty(self):
empty_set = new(self)
placeholder = new(self)
for element in self:
placeholder.add(element)
if empty_set == placeholder: # If both are equal
return False # means self is empty
else:
return True # means self is not empty
class DictSet(Set):
def __init__(self, elements=[]):
rep = self.rep = {}
for element in elements:
rep[element] = element
def add(self, x):
self.rep[x] = x
# Testing code
if __name__ == '__main__':
e = DictSet([1, 2, 3, 4, 19, 31, 27, 0])
t = DictSet([1, 2, 3, 4])
print(t.rep)
# Testing DictSet
inter = e.intersection(t)
uni = e.union(t)
diff = e.difference(t)
eq = e.equals(t)
print('The intersection of the DictSets is:', inter)
print('The union of the Dictsets is:', uni)
print('The difference of the DictSets is:', diff)
print('Are the two DictSets equal?', eq)
I've tried rewriting SetIterator as:
class SetIterator:
def __init__(self, s):
self.elements = **s.rep**
self.index = 0
def __next__(self):
try:
current_element = self.elements[self.index]
except IndexError:
raise StopIteration()
self.index += 1
return current_element
However I still get the same error and my ListSet prints out the correct sets.