比较对象方法导致 3.8 中的不同结果

Comparing object methods leads to different results in 3.8

考虑这个简单的问题 class:

class A:
    def method(self): pass
    def __eq__(self, other): return True

现在,如果我创建 class 的两个实例并比较它们的 'method' 属性,我会在 Python 3.7 和 3.8 中得到不同的结果:

meth1 = A().method
meth2 = A().method
print(meth1 == meth2)  # True in 3.7, False in 3.8

这是怎么回事?为什么方法在 3.7 中相等,但在 3.8 中不相等?这和__eq__有什么关系?

发生的事情是 this commit based on issue 16171610 (and this discussion on python-dev).

有这些(选定的)评论:

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.

其次是

All in all I think that this part was an accident and never designed;

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 '=='.

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.

所以这似乎被认为是 bugfix/feature 因为绑定方法只有在绑定到同一实例时才应该相等,而不是在实例被认为相等的情况下。在 Python <= 3.7 中,绑定方法相等调用实例的 instance1 == instance2 的等效项(因此调用您的 __eq__),而在 Python 3.8 中它检查是否 instance1 is instance2.


相应的变更日志项目可以在 section "Python 3.8.0 alpha 1" 中找到 - 这是一个很长的项目列表,所以我在这里包含了一份副本:

  • 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 of ModuleType and MethodWrapperType instances (methods of user-defined classes and some methods of built-in classes like str.__add__) now depend on the hash and equality of the identity of __self__ instead of its value. MethodWrapperType instances no longer support ordering.