0

I need to compare two object instances for equality and usually I use is when I want to do this; however after a few hours of debugging some code that fails sometimes I found this. Just a code snippet from my debugging.

print "EVENT OBJECT:", id(event.source), "AND BINDING COMPONENT:", id(self.component), "IS THE SAME:", event.source is self.component

which outputs:

EVENT OBJECT: 4 AND BINDING COMPONENT: 4 IS THE SAME: False

However, using == like here:

print "EVENT OBJECT:", id(event.source), "AND BINDING COMPONENT:", id(self.component), "IS THE SAME:", event.source == self.component

outputs:

EVENT OBJECT: 4 AND BINDING COMPONENT: 4 IS THE SAME: True

The result I am after is the second output.

Anyone who can explain? Thought I had it right using is. I am quite new to Python, only started this project a few moths ago coming from .Net and C#.

Edit:

Not a duplicate of this as I thought I did know the difference between is and ==. In fact I did read other posts and they didn't seem to answer my question on why the code in the post behaves as it does.

Update:

Here's a snippet of the init method where I store the component.

def __init__(self, component, *bindings):

    self.__dict__['component'] = component
    print "COMPONENT ID:", hex(id(component)), "COMPONENT IN SELF ID", hex(id(self.component))
    self.__dict__['_bindings'] = bindings

This outputs:

COMPONENT ID: 0x18 COMPONENT IN SELF ID 0x18

And then in the event handler:

print "EVENT OBJECT:", hex(id(event.source)), "AND BINDING COMPONENT:", hex(id(self.component)), "IS THE SAME:", event.source is self.component

I get this output:

EVENT OBJECT: 0x18 AND BINDING COMPONENT: 0x18 IS THE SAME: False

Claus Nielsen
  • 476
  • 6
  • 11
  • 2
    Possible duplicate of [Is there a difference between \`==\` and \`is\` in Python?](https://stackoverflow.com/questions/132988/is-there-a-difference-between-and-is-in-python) – James Jan 18 '18 at 12:28
  • 2
    I bet you shadowed the builtin `id()`, because the fact that `a is b` must be strictly equivalent to `id(a) == id(b)` is garanteed by the language. – bruno desthuilliers Jan 18 '18 at 13:03
  • Except for `event.source` and `self.component` being computed attributes that return a new instance each time and a case of bad luck where they happen to reuse the same memory location I can't see how else you could get that result, and even then the odds you _persistenly_ get the same ids back in a reproductible way are rather low. – bruno desthuilliers Jan 18 '18 at 13:08
  • 1
    We're going to need an [MCVE](https://stackoverflow.com/help/mcve) if we're going to figure this one out. There's just too much unexplained in the example you've given that this could be any number of strange things. Currently I'm with @brunodesthuilliers - the most likely explanation based on your example is that `id()` has been overwritten. – Andrew Gelnar Jan 18 '18 at 13:47
  • @AndrewGelnar Will try make one. Just did a quick test `print id` just before the comparison and it outputs "" – Claus Nielsen Jan 18 '18 at 14:31
  • Probably unrelated but why do you set `self.__dict__['component']` instead of setting `self.component` directly ? – bruno desthuilliers Jan 18 '18 at 15:31
  • I don't anymore, tried changing it to see if it changed anything. I earlier used the `__setattr__` method and I wanted to omit triggering this in the `__init__` method. However it didn't change anything – Claus Nielsen Jan 18 '18 at 15:34
  • This being said, we can't help further without a MCVE. I don't know which Python version you're using but it's highly unlikely that any python release would ship with such a major bug as identity testing being broken, so the problem has to be elsewhere, and trying to reproduce it will most probably lead you to the answer. – bruno desthuilliers Jan 18 '18 at 15:37

1 Answers1

-1

The is operator returns True only when two objects point to the same variable. Consider the following case:

>>> x = [5, 2, 1]
>>> print(hex(id(x)))
'0x7fcefeb45bc8'
>>> y = [5, 2, 1]
>>> print(hex(id(y)))
'0x7fcefeb45b88'
>>> print x is y
False
>>> z = y
print(hex(id(z)))
'0x7fcefeb45bc8'
>>> print y is z
True
Adeel Ahmad
  • 1,033
  • 1
  • 11
  • 24
  • I did set `self.component` using `=` earlier and the component instance stored should be the same as the one in the event. As shown in the code snippets, calling `id` on both objects returns the same value isn't that what `is` does as well? – Claus Nielsen Jan 18 '18 at 12:43
  • @ClausNielsen The issue is not with the value, `is` is not an equality operator. It only checks whether both objects have the same reference / address. – Adeel Ahmad Jan 18 '18 at 12:45
  • @ClausNielsen You can check the memory address using `hex(id(x))`. – Adeel Ahmad Jan 18 '18 at 12:50
  • The memory address is the same for the two objects using `hex(id(x))`. – Claus Nielsen Jan 18 '18 at 12:53
  • @ClausNielsen I have updated my answer with the memory addresses of all variables. Are you printing the memory addresses after assigning them using `=`? In any case, please update your question with this information. – Adeel Ahmad Jan 18 '18 at 12:57
  • @AdeelAhmad the fact that CPython uses memory address as id is an implementation detail. The only important thing is whether `id(x) == `id(y)` - the value of `id(object)` is garanteed to be unique for the lifetime of a given object (IOW you will never have two objects with the same id at a given time in a given process). – bruno desthuilliers Jan 18 '18 at 12:58
  • @AdeelAhmad Have updated the question with the init method where the component is set. – Claus Nielsen Jan 18 '18 at 13:44