返回介绍

建议16:分清 == 与 is 的适用场景

发布于 2024-01-30 22:19:09 字数 2087 浏览 0 评论 0 收藏 0

在判断两个字符串是否相等的时候,混用is和==是很多初学者经常犯的错误,造成的结果是程序在不同情况下表现不一。先来看一个例子:

>>> a = "Hi"
>>> b = "Hi"
>>> a is b
True
>>> a == b   #is 
和 == 
结果一样
True
>>> a1 = "I am using long string for testing"
>>> b1 = "I am using long string for testing"
>>> a1 is b1   #is
的结果为False
False
>>> a1 == b1   # ==
的结果为True
。两者并不一样
True
>>> str1 = "string"
>>> str2 = "".join(['s','t','r','i','n','g'])
>>> print str2
string
>>> str1 is str2
False
>>> str1 == str2     #== 
和is
的结果在这种情况下也不一样
True

造成这种奇怪现象的原因是什么呢?为什么在有些情况下is和==输出相同而在有些情况下又不相同呢?我们来分析一下:首先通过id()函数来看看这些变量在内存中具体的存储空间,为了方便讨论问题,用表2-1来表示上例具体结果。

表2-1 不同变量组id()以及is和==的求值结果

从表格中可以清晰地看到,is和==在验证两个字符串是否相等的时候表现确实不一致,显然混用或者将它们等同起来是存在风险的。那么字符串的比较到底是用is还是用==呢?先来看看Python官方文档中对这两种操作的如下表2-2所示。

表2-2 两种操作的意义

is表示的是对象标示符(object identity),而==表示的意思是相等(equal),显然两者不是一个东西。实际上,造成上面输出结果不一致的根本原因在于:is的作用是用来检查对象的标示符是否一致的,也就是比较两个对象在内存中是否拥有同一块内存空间,它并不适合用来判断两个字符串是否相等。x is y仅当x和y是同一个对象的时候才返回True,x is y 基本相当于id(x) == id(y)。而==才是用来检验两个对象的值是否相等的,它实际调用内部__eq__()方法,因此a == b相当于a.__eq__(b),所以==操作符是可以被重载的,而is不能被重载。一般情况下,如果x is y为True的话x == y的值也为True(特殊情况除外,如NaN,a = float('NaN');a is a 为True,a==a为false),反之则不然。

弄清楚了is和==之间的区别,再来看上述表格中的输出也就不难理解了。但如果再细心一点也许会发现第1组(标注①)中a和b的id值一样,也就是说它们在内存中是同一个对象,而第二组(标注②)中a1和b1的id值却不一样。这又是为什么呢?这是Python中的string interning(字符串驻留)机制所决定的:对于较小的字符串,为了提高系统性能会保留其值的一个副本,当创建新的字符串的时候直接指向该副本即可。因此标注①中“Hi”在系统内存中实际上只有一个副本,所以a和b的id值是一样的;而标注②中a1和b1是长字符串,并不会驻留,Python内存中各自创建了对象来表示a1和b1,这两个对象拥有相同的内容但对象标示符却不相同,所以==的值为True而is的值为False。

注意

判断两个对象相等应该使用==而不是is。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文