Consider this simple class:
class A:
def method(self): pass
def __eq__(self, other): return True
Now if I create two instances of the class and compare their 'method'
attributes, I get different results in Python 3.7 and 3.8:
meth1 = A().method
meth2 = A().method
print(meth1 == meth2) # True in 3.7, False in 3.8
What's going on here? Why are the methods equal in 3.7 but not in 3.8? And what does this have to do with __eq__
?
What happened is this commit based on issue 16171610 (and this discussion on python-dev).
With these (selected) comments:
It seems unlogical to me that whether or not the instance methods of two different instances are equal or not depends on the equality of the instance.
followed by
All in all I think that this part was an accident and never designed;
and
I think it makes little sense that the equality test for the instance methods takes the equality of the instances into account. Imho, this behaviour is inconsistent with the principle of no surprises. The correct behaviour (again imho of course) is that instance methods only compare equal to the same instance method of the same instance, where 'same instance' is based on 'is' not on '=='.
and
This change can be considered as a bugfix, but since it can break the user code (unlikely), it may be safer to merge it only in 3.8 and expose as a new feature.
So this seems to be considered a bugfix/feature because bound methods should only be equal if they are bound on the same instance, not if the instances are considered equal. In Python <= 3.7 the bound method equality calls the equivalent of instance1 == instance2
(thus calling your __eq__
) of the instance while in Python 3.8 it checks if instance1 is instance2
.
The corresponding changelog item can be found in section "Python 3.8.0 alpha 1" - it's a long list of items, so I included a copy here:
- bpo-1617161: The hash of
BuiltinMethodType
instances (methods of built-in classes) now depends on the hash of the identity of __self__ instead of its value. The hash and equality ofModuleType
andMethodWrapperType
instances (methods of user-defined classes and some methods of built-in classes likestr.__add__
) now depend on the hash and equality of the identity of __self__ instead of its value.MethodWrapperType
instances no longer support ordering.