Reputation: 751
I would like to implement an __eq__()
method for an custom class Vertex
.
However, when I carefully think about the problem, I find it is quite weird.
For example
class Vertex():
def __init__(self,node):
self.id = node
self.adjacent = {}
However for the adjacent dict
, it store the data like this:
{neighbour_vertex1 : edge, neighbour_vertex2 : edge, ....}
If I want to implement the __eq__()
method, it should look like:
def __eq__(self,other):
return self.id == other and self.adjacent == other.adjacent
but the self.adjacent == other.adjacent
requires to compare the dicts
{neighbour_vertex1 : edge, neighbour_vertex2 : edge, ....}
{neighbour_vertex1 : edge, neighbour_vertex2 : edge, ....}
In order to compare them, I have to define the comparison function for neighbout_vertex
which indeed is an instance of class Vertex
.
I think it is like a chicken or egg question, any suggestion is appreciated.
Edit: example
class Vertex(object):
def __init__(self,id):
self.id = id
self.adjacent ={}
def add_vertex(self,obj):
self.adjacent.update(obj)
def __eq__(self,other):
return self.id == other.id and self.adjacent == other.adjacent
def __hash__(self):
return hash(id(self))
obj1 = Vertex("one")
obj2 = Vertex("two")
temp = {obj2:"connect 1-2"}
obj1.add_vertex(temp)
obj1s = Vertex("one")
obj2s = Vertex("two")
temp2 = {obj2s:"connect 1-2"}
obj1s.add_vertex(temp2)
if obj1 == obj1s:
print("True")
else:
print("False")
I came out with a simple example, first I do not want to modify the hash function, how can I modify the __eq__function to make the above code output
True
instead of False
Upvotes: 0
Views: 78
Reputation: 280544
I don't think you need an __eq__
override here at all. With the design you've chosen, it doesn't make sense for two different instances of Vertex
to represent "the same vertex", and two Vertex
instances should only compare equal if they are actually the same object. The default __eq__
implementation already gives you that behavior.
If you do want different instances of Vertex
to compare equal, then you need to think about your design first. For example, your definition of __hash__
as hash(id(self))
only makes sense if equality works by identity, so your __hash__
will need to be changed. You'll also need to think about things like, what if vertices a
and b
both have self.id = 1
and self.adjacent = {c: 'asdf'}
, but c
has self.adjacent = {b: 'asdf'}
? Are a
and b
equal? You're going to have to come up with a precise definition of the concept of equality you want to use.
One possible redesign would be to move adjacency tracking out of the vertex objects. If vertex objects only have self.id
, and edges are tracked externally by some sort of Graph object, then it could make sense to compare Vertex objects "by value". At that point, it might make more sense to eliminate the Vertex class entirely, though.
Upvotes: 3
Reputation:
@Ralf suggested comparing only the id
attribute. This is probably the best solution, and you should absolutely go with that if possible.
If not, what is the structure of your vertices? Is it like a tree where adjacency only goes one way? Then writing it like that is fine; eventually you'll run out of nodes.
If the vertices can loop back, we'll have to do something more complicated. The basic trick is to maintain a stack of vertices you haven't visited, and a list of nodes you've already compared. With each loop, pop the top element off the stack. If you see anything that would make the elements compare false, you can return. Otherwise, put the adjacent nodes on the stack if you haven't visited them before, update the visited nodes, and keep going.
(I won't be making the effort to provide a code sample.)
Upvotes: 2