为什么当两个对象 point 和 b 时,我的相等方法为什么会产生 True strong>是否指向内存中的2个不同对象?
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()
答案 0 :(得分:2)
id
对象中的 Point
是不同的,因为它们是不同的对象,并且没有针对它们的缓存/中间机制(这是错误的,因为它们是可变的)。
==
之所以有效,是因为在==
上调用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默认==
运算符只有对象标识才能执行比较。 / p>
但是==
的目的是比较对象内容,而不是 id 。如上所示,对测试身份的相等性方法进行编码可能会导致意外。
在Python中,当人们使用==
时,如果值相等,他们期望对象相等。身份是一个实现细节,只需忘记它。
(Python的先前版本要求您也定义__ne__
,因为它不是__eq__
的倒数,并且会导致奇怪的错误)
简而言之:除非您要编写非常复杂的低级程序,否则请不要使用is
(除了is None
惯用语)或id
缓存和怪异的东西,或者在调试程序时。
答案 1 :(得分:0)
Python会缓存小整数(在[-5,256]范围内),因此id(self.x) == id(other.x) and id(self.y) == id(other.y)
是True
。由于self.x
和other.x
是内存中的相同对象。查找比较这两个对象的另一种方法,或者摆脱自定义__eq__
并使用默认方法(在这种情况下,Python将为False
返回point == Point(2, 3)
)。
有关该问题的更多信息,请参见this答案。