Python中对象的比较操作==和is区别详析
本文详细解析Python中==和is两种比较操作符的区别。==用于比较对象的值是否相等,而is用于判断两个变量是否指向内存中的同一个对象。文章通过整数对象池和字符串intern机制解释了特殊现象,并建议在比较单例(如None、True/False)时使用is以提高性能。
前言
在Python语言中,对象比较主要涉及两种操作符:==和is。尽管两者都能用于判断操作符两侧变量的关系,但它们的具体行为存在显著差异。下文将通过具体示例深入剖析这两者的区别。
比较操作符通常用于条件语句,如下示例:
if a == b:
pass
if a is False:
pass
== 与 is 的区别
== 操作符的核心功能是判断两个对象的值是否相等。可以将其类比为:小明拥有一块劳力士手表,小李也拥有一块同款劳力士手表,此时我们判定这两块手表在价值或外观上是相等的。
小明的手表 = 劳力士 小李的手表 = 劳力士 小明的手表 == 小李的手表
is 操作符则用于比较对象的身份标识(identity),即检查两个变量是否指向内存中的同一地址。如果两个对象的身份标识相同,说明它们引用的是内存中的同一个对象实例。例如,小明的父亲称呼他为“儿子”,而小明的女朋友称呼他为“老公”,虽然称呼不同,但指代的都是小明这个人,即同一个对象。
爸爸的儿子 = 小明 女朋友的老公 = 小明 爸爸的儿子 is 女朋友的老公
接下来通过代码示例来直观展示 == 与 is 的具体区别:
>>> a = [1, 2, 3]
>>> b = [1, 2, 3]
>>> a == b
True
>>> a is b
False
>>> id(a)
24603664
>>> id(b)
24603144
>>> a = [1, 2, 3]
>>> b = a
>>> a == b
True
>>> a is b
True
>>> id(a)
24604144
>>> id(b)
24604144
在Python中,id()函数接收一个对象作为参数,并返回该对象在内存中的地址。
通过上述代码分析可以得出结论:== 操作符仅比较两个对象的值是否相等,而不关心它们是否为同一个对象;而 is 操作符并不比较值是否相等,而是确认两个变量是否指向同一个对象。如果两个变量指向同一个对象,那么它们的值必然相等。
Python 小整数对象池
前文的两段代码已经展示了 == 与 is 的基本区别,但Python中存在一些特殊情况。请看下面的例子:
>>> a = 5
>>> b = 5
>>> a == b
True
>>> a is b
True
>>> id(a)
1730274128
>>> id(b)
1730274128
>>> a = 257
>>> b = 257
>>> a == b
True
>>> a is b
False
>>> id(a)
48558688
>>> id(b)
48558720
上述代码看起来可能有些反直觉,同样的比较操作,仅仅因为数字不同,结果就出现了差异。
造成这种现象的根本原因在于Python自身的实现机制。出于性能优化的考虑,Python解释器在启动时,会将 -5 到 256 范围内的整数预先创建并驻留在内存中。当我们需要创建值位于 -5 到 256 之间的整数时,Python不会重新开辟新的内存空间,而是直接返回已存在的对象引用。
然而,如果新创建的整数不在这个预定义范围内,Python就会为每个变量单独开辟独立的内存空间,导致即使值相同,它们的内存地址也不同。
Python intern 机制
再来看一个关于字符串比较的例子:
>>> a = 'hello world'
>>> b = 'hello world'
>>> a == b
True
>>> a is b
False
>>> id(a)
49465408
>>> id(b)
49465448
>>> a = 'hello'
>>> b = 'hello'
>>> a == b
True
>>> a is b
True
>>> id(a)
49429152
>>> id(b)
49429152
基于之前对整数比较的理解,你可能已经猜到上述代码结果不同的原因。事实上,这也是Python出于性能优化的考虑,但这次采用的机制被称为 intern(驻留)机制。
关于 intern 机制的具体实现原理较为复杂,此处不再深入展开,未来可能会专门撰文介绍。总之,你需要了解的是,在某些特定场景下,Python会对字符串启用 intern 机制以提升性能,这直接导致了上述示例中代码执行结果的差异。
== 与 is 各自的适用场景
那么,在实际开发中,何时应该使用 ==,何时又该使用 is 呢?
当我们需要比较一个变量与单例(Singleton)对象时,应当使用 is;而在其他大多数情况下,通常使用 ==。
例如,当我们将一个变量与 True 或 False 进行比较时,推荐使用 is,因为使用 is 进行比较的速度通常比使用 == 更快。
使用 is 比较对象时,Python只需判断它们是否指向同一块内存地址,这是一个非常轻量级的操作。相比之下,使用 == 比较对象时,Python会调用对象的 __eq__() 方法。由于 __eq__() 方法通常会被重载以执行复杂的内部逻辑,因此其执行速度相对较慢。
以下代码展示了一个重载对象 __eq__() 方法的示例:
class MyList(object):
def __init__(self, *args):
self._list = [*args]
def __eq__(self, other):
result = False
for i in self._list:
for j in other._list:
if i == j:
break
else:
break
else:
result = True
return result
li_1 = MyList(1, 2, 3)
li_2 = MyList(1, 2, 3)
print(li_1 == li_2) # True
你可以尝试修改 __eq__() 方法内部的逻辑,以观察其对比较结果的影响。
总结
到此为止,关于Python中对象比较操作 == 和 is 的区别已介绍完毕。如需了解更多相关内容,建议搜索本站以前的文章或继续浏览下方的相关文章。希望大家今后能多多支持本站!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













