比较运算符“==”表示值相等还是引用相等?

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__(),在错误比较的情况下返回NotImplementedTrue 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中比较字符串的内容是不是相等内部是如何比较的?还有比较字符串与比较它的哈希值哪个快?

JavaScript关系运算符 赋值运算符

Javascript 中 ==(相等运算符) 和 ===(严格相等运算符) 区别

==,=和equals()区别

php运算符

python 比较运算符和逻辑运算符