Search code examples
pythoninstance-methods

Why does 'is' not work when comparing instance methods in python


I've noticed that sometimes instance methods do not compare as identical (using is rather than ==), even when they relate to the same bound instance method e.g.

>>> class A(object):
...     def f(self):
...             print "hi"
... 
>>> a = A()
>>> f1 = a.f
>>> f2 = a.f
>>> f1 is f2
False
>>> f1 == f2
True

I've ended up using == to check to see if two variables refer to the same bound method, but I was wondering if anyone knew why is does not behave as I would expect?


Solution

  • methods are implemented as descriptors -- So each time you access the f member, a new function is created. You can see this by looking at their ids...

    >>> class A(object):
    ...     def f(self):
    ...         pass
    ... 
    >>> a = A()
    >>> f1 = a.f
    >>> f2 = a.f
    >>> id(f1)
    4325305232
    >>> id(f2)
    4325818528
    

    To be a little more clear what I mean when I say that they are implemented via descriptors, the following expressions:

    a = A()
    func = a.f
    

    are equivalent to:

    a = A()
    func = A.f.__get__(a, A)
    

    Clearly you don't want to be writing the latter all the time, so the shortcut is pretty nice :-).

    With that said, this starts to explain how a bound method knows what self is since a (which is self in the method) gets passed to __get__ which is what constructs the bound method.