python - 相等运算符为内存中的 2 个不同对象生成 True
问题描述
为什么当 2 个对象指向和b指向内存中的 2 个不同对象时,我的相等方法会产生True ?
import math
def main():
point = Point(2, 3)
print(point == Point(2, 3))
b = Point(2, 3)
print(id(point), id(b))
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def distance_from_origin(self):
return math.hypot(self.x, self.y)
def __eq__(self, other):
return id(self.x) == id(other.x) and id(self.y) == id(other.y)
def __repr__(self):
return f"Point({self.x!r}, {self.y!r})"
def __str__(self):
return f"{self.x!r}, {self.y!r}"
如果名称== '主要': main()
解决方案
id
对象是不同的Point
,因为它们是不同的对象,并且它们没有缓存/内部机制(这是错误的,因为它们是可变的)。
==
有效,因为在调用==
on 时Point
,您调用__eq__
并且它的编码如下:
def __eq__(self, other):
return id(self.x) == id(other.x) and id(self.y) == id(other.y)
所以,这是错误的,但由于在 CPython 中对从 -5 到 256 的整数进行了实习,它大部分时间都有效(进一步的测试表明它适用于更大的值,但不能保证)。反例:
a = 912
b = 2345
point = Point(a, b)
print(point == Point(456*2, b))
False
即使你会得到456*2 == 912
重写为这样,这样你就不会对大整数感到惊讶:
def __eq__(self, other):
return self.x == other.x and self.y == other.y
如果删除此__eq__
方法,您将得到False
,在这种情况下,==
未知对象上的 Python 默认运算符仅具有执行比较的对象标识。
但目的==
是比较对象内容,而不是ids。如上所示,编写一个测试身份的相等方法可能会导致意外。
在 Python 中,当人们使用 时==
,如果值相等,他们希望对象是相等的。身份是一个实现细节,别管它了。
(以前版本的 Python 也需要您定义__ne__
,因为它不会自动反转__eq__
并且可能导致奇怪的错误)
简而言之:不要使用is
(除了is None
成语),或者id
除非你正在编写一个非常复杂的低级程序,其中包含缓存和奇怪的东西,或者在调试你的程序时。
推荐阅读
- javascript - 使用 react-router 后,onClick 事件不会在第一次触发该功能,之后可以正常工作
- vim - 不带走功能的领导键
- c - 使用 qsort 对 C 中的结构数组进行排序
- python - Django 模型,表单字段
- c# - 有没有办法在一小段延迟后加载场景?
- python - 在 discord.py 中保存数据
- azure-iot-hub - 具有自定义文件名格式的 ADLS Gen2 的 Azure IoT 中心端点
- wordpress - 使用 wp-cli 变量嵌套 if-then 语句
- python - 在 Librosa 中获取与 STFT 相关的频率
- c# - 为什么 Avicap32.capCreateCaptureWindow 关闭?