>>> from env_helper import info; info()
页面更新时间: 2023-08-25 16:07:42
运行环境:
    Linux发行版本: Debian GNU/Linux 12 (bookworm)
    操作系统内核: Linux-6.1.0-11-amd64-x86_64-with-glibc2.36
    Python版本: 3.11.2

2.8. 分清 ==is 的适用场景

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

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

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

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

</table>

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

  • is : object identity

  • == : equal

is 表示的是对象标示符(object identity ),而 == 表示的意思是相等(equal ),显然两者不是一个东西。 实际上,造成上面输出结果不一致的根本原因在于: is 的作用是用来检査对 象的标示符是否一致的,也就是比较两个对象在内存中是否拥有同一块内存空间,它并不适合用来判断两个宇符串是否相等。 x is y 仅当 xy 是同一个对象的时候才返回 Truex is b 基本相当于 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组(标注①)中ab的id值一样,也就是说它们在内存中是同一个对象,而第二组(标注②)中a1b1的id值却不一样。这又是为什么呢?这是Python中的 string interning (宇符串驻留)机制所决定的:对于较小的字符串,为了提高系统性能会保留其值的一个副本,当创建新的字符串的时候直接指向该副本即可。因此标注①中“Hi”在系 统内存中实际上只有一个副本,所以ab的id值是一样的;断标注②中a1b1是长字符串,并不会驻留,Python内存中各自创建了对象来表示a1b1 ,这两个对象拥有相同的内容但对象标示符却不相同,所以==的值为True而的值为False。

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

By Bu Kun
© Copyright From 2020. Build on 2024-1-15. by BU Kun @ OSGeo China Chapter.

id()

is

==

a = “Hi”①

14085224

True

True

b = “Hi”①

14085224

a1 = “I am using long string for testing”②

13003368

False

True

b1 = “I am using long string for testing”②

14078152

str1 = “string”

13256448

False

True

str2 = “” . join([‘s’,‘t’,‘r’,‘i’,‘n’,‘g’])

14056544