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 wh
Python doesn't keep a canonical foo.bar object for every instance foo of class Foo. Instead, a method object is created when Python evaluates foo.bar. Thus,
foo.bar is not foo.bar
As for ==, things get messy. Python 3.8 fixed method comparison so two methods are equal if they represent the same method of the same object, but on lower versions, the behavior is inconsistent.
Python has a surprisingly large number of method object types, depending on whether the method was implemented in Python or one of the several ways methods can be implemented in C. Before Python 3.8, these method object types respond to == differently:
== compares the methods' __func__ and __self__ attributes, returning True if the method objects represent methods implemented by the same function and bound to equal objects, rather than the same object. Thus, x.foo == y.foo will be True if x == y and foo is written in Python.__self__ and an internal thing analogous to __func__, again returning True if the methods have the same implementation and are bound to equal objects.Thus, if you run the following code on a Python version below 3.8:
class Foo(object):
def __eq__(self, other):
return True if isinstance(other, Foo) else NotImplemented
def foo(self):
pass
print(Foo().foo == Foo().foo)
print([].__repr__ == [].__repr__)
print([].append == [].append)
You get the following bizarre output:
True
True
False
To get the Python 3.8 semantics on lower versions, you can use
meth1.__self__ is meth2.__self__ and meth1 == meth2