I would like to be able to test whether two callable objects are the same or not. I would prefer identity semantics (using the "is" operator), but I've discovered that when methods are involved, something different happens.
#(1) identity and equality with a method
class Foo(object):
def bar(self):
pass
foo = Foo()
b = foo.bar
b == foo.bar #evaluates True. why?
b is foo.bar #evaluates False. why?
I've reproduced this with both Python 2.7 and 3.3 (CPython) to make sure it's not an implementation detail of the older version. In other cases, identity testing works as expected (interpreter session continued from above):
#(2) with a non-method function
def fun(self):
pass
f = fun
f == fun #evaluates True
f is fun #evaluates True
#(3) when fun is bound as a method
Foo.met = fun
foo.met == fun #evaluates False
foo.met is fun #evaluates False
#(4) with a callable data member
class CanCall(object):
def __call__(self):
pass
Foo.can = CanCall()
c = foo.can
c == foo.can #evaluates True
c is foo.can #evaluates True
According to the question How does Python distinguish callback function which is a member of a class?, a function is wrapped when bound as a method. This makes sense and is consistent with case (3) above.
Is there a reliable way to bind a method to some other name and then later have them compare equal like a callable object or a plain function would? If the "==" does the trick, how does that work? Why do "==" and "is" behave differently in case (1) above?
Edit
As @Claudiu pointed out, the answer to Why don't methods have reference equality? is also the answer to this question.