2

Recently I saw several questions about unexpected behavior when performing is test on the same bound method of the same object. Specifically, please see questions Why does `instance_of_object.foo is instance_of_object.foo` evaluate False? and Two methods inherited from one method in class are different in instances, aren't they?

Let's describe the issue, for example, as described in the first linked question above. Let's assume a class:

class A(object):
  def foo(self):
    pass

Then the strange thing observed in that question is that if we create an object of type A such as a = A() then test a.foo is a.foo fails (returns False). According to answer given in https://stackoverflow.com/a/48736729, a new method instance is created every time a bound method is accessed.

If that is correct and explains why a.foo is a.foo is always False, why theids of these presumably distinct method objects are equal:

>>> id(a.foo) == id(a.foo)
True
AGN Gazer
  • 8,025
  • 2
  • 27
  • 45

1 Answers1

2

You're wrestling with illusions ;-) In

id(a.foo) == id(a.foo)

the first a.foo is created, its id is obtained, and then the bound method immediately becomes garbage. In CPython, reference counting causes its memory to be freed at once. The same memory happens to be reused (although there's no guarantee this will happen) when the second a.foo is created. ids are only guaranteed unique across a collection of objects simultaneously alive.

In contrast, in

a.foo is a.foo

both sides are simultaneously alive, so the distinct a.foo objects cannot occupy the same memory. To do a similar thing with ids, you have to arrange to keep keep both of them alive long enough for the id comparison to complete; e.g.,

>>> a1 = a.foo
>>> id(a1) == id(a.foo)
False
Tim Peters
  • 67,464
  • 13
  • 126
  • 132