比较运算符“==”表示值相等还是引用相等?
Posted
技术标签:
【中文标题】比较运算符“==”表示值相等还是引用相等?【英文标题】:Comparison operator "==" for value equality or reference equality? 【发布时间】:2022-01-17 15:46:08 【问题描述】:很多教程都声明==
比较运算符用于值相等,就像在这个answer 中,引用:
==
用于值相等。当您想知道两个对象是否具有相同的值时,请使用它。is
用于引用相等。当您想知道两个引用是否指向同一个对象时,请使用它。
但是,我发现 Python doc 说:
x==y
呼叫x.__eq__(y)
。默认情况下,object
通过使用is
实现__eq__()
,在错误比较的情况下返回NotImplemented
:True if x is y else NotImplemented
。”
==
运算符的默认行为似乎是像 is
运算符那样比较参考质量,这与这些教程所说的相矛盾。
那么我到底应该使用==
做什么?值相等还是引用相等?或者它只是取决于你如何实现__eq__
方法。
我认为Value comparisons 的文档已经清楚地说明了这个问题:
运算符
<
、>
、==
、>=
、<=
和!=
比较两个对象的值。对象的值在 Python 中是一个相当抽象的概念。比较运算符实现了对象值的特定概念。可以将它们视为通过它们的比较实现来间接定义对象的值。
默认相等比较的行为,即具有不同身份的实例始终不相等,可能与需要对对象值和基于值的相等进行合理定义的类型形成对比。此类类型需要自定义它们的比较行为,事实上,许多内置类型已经做到了这一点。
相等比较的默认行为(
==
和!=
)基于对象的标识。因此,具有相同身份的实例的相等比较导致相等,而具有不同身份的实例的相等比较导致不平等。这种默认行为的动机是希望所有对象都是自反的(即x is y
暗示x == y
)。
它还包括一个列表,描述了最重要的内置类型(如数字、字符串和序列等)的比较行为。
【问题讨论】:
【参考方案1】:object
使用is
实现__eq__()
,但标准库中的许多类使用值相等来实现__eq__()
。例如:
>>> l1 = [1, 2, 3]
>>> l2 = [1, 2, 3]
>>> l3 = l1
>>> l1 is l2
False
>>> l1 == l2
True
>>> l1 is l3
True
在你自己的类中,你可以实现__eq__()
,因为它是有意义的,例如:
class Point():
def __init__(self, x, y):
self.x = x
self.y = y
def __eq__(self, other):
return self.x == other.x and self.y == other.x
【讨论】:
【参考方案2】:one = 1
a = one
b = one
if (a == b): # this if works like this: if (1 == 1)
if (a is 1): # this if works like this: if (int.object(1, memory_location:somewhere) == int.object(1, memory_location:variable.one))
因此,a is 1 不起作用,因为它的参数没有指向同一个位置。
【讨论】:
a is 1
引发 SyntaxWarning
(在 Python 3.9 中测试)
直到关于SyntaxWarning
。整洁的。根据快速测试,它看起来像是在 a is 1
从 Python 3.8 开始生成的。
实际上,a is 1
在我的测试中返回了True
,我认为这是因为Python 有一个用于像1
这样的常见整数的缓存池,并且它们只创建一次。【参考方案3】:
这完全取决于__eq__
做了什么。 object
类型的默认 __eq__
的行为类似于 is
。一些内置数据类型使用它们自己的实现。例如,如果两个列表的所有值都相等,则它们是相等的。你只需要知道这一点。
【讨论】:
【参考方案4】:用一个简单的定义来添加你的思维过程,
相等运算符==
比较两个操作数的值并检查值是否相等。而is
运算符检查两个操作数是否引用同一个对象(存在于同一个内存位置)。
简而言之,is
检查两个引用是否指向同一个对象。==
检查两个对象是否具有相同的值。
例如:
a=[1,2,3]
b=a #a and b point to the same object
c=list(a) #c points to different object
if a==b:
print('#') #output:#
if a is b:
print('##') #output:##
if a==c:
print('###') #output:##
if a is c:
print('####') #no output as c and a point to different object
【讨论】:
以上是关于比较运算符“==”表示值相等还是引用相等?的主要内容,如果未能解决你的问题,请参考以下文章
Java中比较字符串的内容是不是相等内部是如何比较的?还有比较字符串与比较它的哈希值哪个快?