高阶python | is 与 ==

文章解释了Python中is和==的区别,is比较的是对象的身份标识,而==比较的是数据值。对于可变类型如列表,即使内容相同,is也会返回False,因为它们是不同的对象。对于不可变类型如字符串,is在某些情况下可能导致误判,因为字符串的拼接可能创建新的对象。此外,文章提到了Python对小整数的缓存机制,使得相同整数的id可能相同。建议在大量字符串拼接时使用join函数以优化内存使用。
摘要由CSDN通过智能技术生成

python版本:3.10.0

(对于文中一些可能产生疑问的部分对应篇末有补充内容帮助读者充电,请注意“<>”提示)

在python中,经常会搞混is与==的用法

其实很简单,首先俩个比较都是要求比较的两者某条件相等的

其次,is是用来比较身份标识的,==是用来比较数据值

Python 中,对于任意的变量都具有三个基本要素:分别是 id,type,value。其中 id 为身份标识,即唯一能识别变量的标志,type 为数据类型,value 为数据值。

例如下面的例子:

a_list = [1, 2, 3]
b_list = [1, 2, 3]
print(a_list == b_list)
print(a_list is b_list)

True
False

结果为啥不一样呢?

因为两个可变类型数据指向的对象不一样<id()的用法见补充1>

print(id(a_list))
print(id(b_list))

2793639858304
2793643606464

is在不可变数据的比较中慎用

以字符串为例,在字符串的比较中,由于字符串为不可变数据类型,贸然使用is来比较两个字符串是有风险的

我们先展示一种没翻车的版本

s1 = 'i am what i am and that is all that i am'
s2 = 'i am what i am' + ' and that is all that i am'
print(s1 == s2)
print(s1 is s2)
print(id(s1))
print(id(s2))

True
True
2541839741264
2541839741264

因为这个拼接后的字符串与s1指向的字符串相同,所以s2直接指向s1指向的字符串对象,其id也相同,所以这里的is比较结果也相同。<补充3>

而后面这个版本就翻车了

s1 = 'i am what i am and that is all that i am'
s2 = 'i am what i am'
print('s1:', id(s1))
print('s2:', id(s2))
print()
s2 = s2 + ' and that is all that i am'
print(s1 == s2)
print(s1 is s2)
print('s1:', id(s1))
print('s2:', id(s2))

s1: 2061619654992
s2: 2061619581424

True
False
s1: 2061619654992
s2: 2061619653456

 s2是后拼接的,从一开始因为赋值的字符串不一样,所以两个变量的id就不一样,即两个变量是不相同的,即使是后拼接成一样的值,其id也是不相同的,所以比较结果为false

(同时可见字符串拼接的时候会多次申请内存地址和创建新变量,对于大量的字符串拼接,请使用join函数先把所需拼接完成后再赋值给变量)

以整数为例,整数不同于字符串,比较简单,可以用is,但不推荐,能用==来比值达到目的就不要冒着风险使用is<整型的特性见补充4>

a = 11
b = 1
print('a:', id(a))
print('b:', id(b))
print(a == b)
print(a is b)

print()
b = 11
print('a:', id(a))
print('b:', id(b))
print(a == b)
print(a is b)

a: 1744108323376
b: 1744108323056
False
False

a: 1744108323376
b: 1744108323376
True
True

补充内容

1.id()的使用

在Python中,id()函数返回对象的唯一标识符。这个标识符是一个整数,它在对象的生命周期<补充2>内保持不变。标识符可以用于比较两个对象是否相同(即是否是同一个对象)。下面是一个示例:

a = [1, 2, 3]
b = [1, 2, 3]

print(id(a))    # 输出:140592387436232
print(id(b))    # 输出:140592387436552

c = a
print(id(c))    # 输出:140592387436232

print(a is b)   # 输出:False
print(a is c)   # 输出:True

在上面的示例代码中,ab虽然具有相同的值,但它们是不同的对象,因此它们的标识符不同。而将a赋值给c后,ca是同一个对象,它们的标识符相同。最后,使用is运算符可以比较两个对象是否是同一个对象。

2.什么是对象的生命周期

对象的生命周期指的是从对象创建到销毁的整个过程,它可以分为如下几个阶段:

  1. 创建阶段:在创建对象时,系统会为其分配一定的内存空间,并执行构造函数初始化对象的状态。

  2. 使用阶段:对象被创建后,可以通过调用对象的成员函数或访问对象的成员变量来使用它。在使用阶段中,对象可以被多次引用或修改,直到它的生命周期结束。

  3. 销毁阶段:当对象不再被引用或使用时,系统会执行析构函数销毁对象并释放其占用的内存空间。在销毁阶段中,对象的状态会被清空,并且对象所占用的内存空间会被归还给操作系统。

在涉及复杂的对象关系时,对象的生命周期可能会因为对象间的相互引用变得复杂。为了避免对象间的循环引用,可以使用特殊的技巧,例如智能指针等,来管理对象的生命周期。

3.python 同字符串赋值两个不同变量,为什么两个变量的id相同

这是因为在Python中,有个特性叫做字符串常量池(string interning),即对于一些常用的字符串,Python会自动缓存这些字符串对象,每次创建相同的字符串时,实际上是返回同一个对象的引用,这个对象在内存中的位置是不变的,因此两个不同的变量赋值同一个字符串时,它们会共享同一个对象,其id也相同。但是对于不可变类型以外的对象,这个特性并不适用。

4.python 同整型数据赋值两个不同变量,为什么两个变量的id相同

在Python中,对于较小的整数,Python会尝试缓存这些整数以提高性能并减少内存使用。因此,当你创建一个整数时,Python会检查该整数是否已经在缓存中,如果是,则返回缓存中存在的整数的引用,而不是创建一个新的整数对象。这意味着,对于相同的整数,它们的id是相同的,因为它们实际上是同一个对象。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值