5

考虑这个简单的类:

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

现在,如果我创建该类的两个实例并比较它们的'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__

4

1 回答 1

5

发生的事情是基于问题 16171610的提交(以及关于 python-dev 的讨论)。

使用这些(选定的)评论:

在我看来,两个不同实例的实例方法是否相等取决于实例的相等性,这似乎是不合逻辑的。

其次是

总而言之,我认为这部分是一个意外,从未设计过;

我认为实例方法的相等性测试考虑实例的相等性是没有意义的。恕我直言,这种行为不符合不出意外的原则。正确的行为(当然再次恕我直言)是实例方法仅比较等于同一实例的同一实例方法,其中“同一实例”基于“是”而不是“==”。

此更改可被视为错误修复,但由于它可能会破坏用户代码(不太可能),因此仅在 3.8 中合并它并作为新功能公开可能会更安全。

所以这似乎被认为是一个错误修复/功能,因为绑定方法只有在它们绑定在同一个实例上时才应该相等,而不是在实例被认为相等的情况下。在 Python <= 3.7 中,绑定方法相等调用实例的等效项instance1 == instance2(因此调用您的__eq__),而在 Python 3.8 中,它检查 if instance1 is instance2


相应的变更日志项目可以在“Python 3.8.0 alpha 1”部分找到——这是一个很长的项目列表,所以我在这里包括了一个副本:

  • bpo-1617161BuiltinMethodType实例(内置类的方法)的哈希现在取决于__self__身份的哈希,而不是它的值。ModuleTypeMethodWrapperType实例(用户定义类的方法和内置类的一些方法,如)的哈希和相等str.__add__性现在取决于__self__标识的哈希和相等性,而不是它的值。MethodWrapperType实例不再支持排序。
于 2019-11-12T17:14:51.887 回答