1

I have a class I've written, MyEdge (it stores two nodes to make an edge for some graphs), and I'm struggling to figure out why isinstance seems to be behaving inconsistently.

I have an object, new_road, that thinks it is in the MyEdge class when I ask it. isinstance(new_road, my_graph.MyEdge) returns False.

When I make a pointer to it, e0 = new_road, isinstance(e0, my_graph.MyEdge), I also get false, which is at least self consistent.

When I make a copy, e1 = my_graph.MyEdge(new_road.nodes), isinstance(e1,my_graph.MyEdge) returns true.

new_road, e0 and e1 all return that their class is 'my_graph.MyEdge', so it seems like isinstance(new_road,my_graph.MyEdge) should be true.

Why is isinstance treating e1 and new_road1 differently?

ipdb> new_road.__class__
<class 'my_graph.MyEdge'>

ipdb> e1 = my_graph.MyEdge(new_road.nodes)

ipdb> e1 is new_road
False

ipdb> e1 == new_road
True

ipdb> e1.__class__
<class 'my_graph.MyEdge'>

ipdb> new_road.__class__
<class 'my_graph.MyEdge'>

ipdb> isinstance(e1,my_graph.MyEdge)
True

ipdb> isinstance(new_road,my_graph.MyEdge)
False

ipdb> new_road1.__class__ is my_graph.MyEdge 
False

ipdb> e1.__class__ is my_graph.MyEdge 
True

I don't know if it's useful, but here is the code for my MyEdge class:

class MyEdge(object):
    """ keeps the properties of the edges in a parcel."""

    def __init__(self, nodes):
        self.nodes = tuple(nodes)
        self.parcel1 = None
        self.parcel2 = None
        self.road = False
        self.barrier = False

    @lazy_property
    def length(self):
        return mgh.distance(self.nodes[0], self.nodes[1])

    @lazy_property
    def rads(self):
        return math.atan((self.nodes[0].y - self.nodes[1].y) /
                         (self.nodes[0].x - self.nodes[1].x))

    def __repr__(self):
        return "MyEdge with nodes {} {}".format(self.nodes[0], self.nodes[1])

    def __eq__(self, other):
        return ((self.nodes[0] == other.nodes[0] and
                 self.nodes[1] == other.nodes[1]) or
                (self.nodes[0] == other.nodes[1] and
                 self.nodes[1] == other.nodes[0]))

    def __ne__(self, other):
        return not self.__eq__(other)

    def __hash__(self):
        return hash(self.nodes)
myaut
  • 11,174
  • 2
  • 30
  • 62
Christa
  • 497
  • 1
  • 4
  • 8

1 Answers1

4

Maybe you reload/reimport/overwrite the class between creating new_road and e1

In [1]: class C(object): pass
In [2]: a = C()
In [3]: class C(object): pass
In [4]: isinstance(a, C)
Out[4]: False

In this example, __class__ of two C() instances looks the same, but they are still different. id() might help:

id(type(e1)), id(type(new_road)), id(my_graph.MyEdge)

All ids should be the same.

Martin Preusse
  • 9,151
  • 12
  • 48
  • 80
  • Thanks! Right now the ids for e1 and my_graph.MyEdge are the same, and new_road is different. I'll look through my code and see if I can figure out where I'm reloading (or something) my_graph. – Christa May 07 '15 at 20:22
  • 1
    So, it turns out that my problem was because I'd copied my code from a folder in dropbox to somewhere else so it would play nice with github, and hadn't removed the dropbox folder from sys.path. Then, I guess I was somehow importing or reloading my_graph twice with the same name from the two different locations. Taking the dropbox path out of my sys.path fixed the problem. – Christa May 07 '15 at 21:04