“==”和“is”有什么区别?一个问题就能暴露你的Python水平

开发 后端
“==”和“is”都是 Python 中的运算符。对于初学者,他们可能会把“ a==b ”解释为“ a 等于 b ”,“a is b”也可以解释为“ a是b ”。这可能就是初学者在 Python 中混淆“ == ”和“ is ”的原因。

可能在网上你经常能看到关于这个问题的答案和解析,但是依然有很多刚开始学习Python的人,不了解这个问题,也不知道为什么问这个问题时会暴露自己是“菜鸟”,这个问题就是:

“==” 和 “is”之间有什么区别?

“==”和“is”都是 Python 中的运算符。对于初学者,他们可能会把“ a==b ”解释为“ a 等于 b ”,“a is b”也可以解释为“ a是b ”。这可能就是初学者在 Python 中混淆“ == ”和“ is ”的原因。

在开始之前,我想先展示一些使用“==”和“is”的例子。

  1. >>> a = 5 
  2. >>> b = 5 
  3. >>> a == b 
  4. True 
  5. >>> a is b 
  6. True 

很简单,对吧? a == b 和 a is b 都返回了结果 True。接下来我们看另一个示例:

  1. >>> a = 1000 
  2. >>> b = 1000 
  3. >>> a == b 
  4. True 
  5. >>> a is b 
  6. False 

WTF ?!? 从第一个示例到第二个示例的唯一变化就是 a 和 b 的值从 5 到 1000。但是返回的结果在 “ ==” 和 “ is” 已经不同。我们再看另一个示例:

  1. >>> a = [] 
  2. >>> b = [] 
  3. >>> a == b 
  4. True 
  5. >>> a is b 
  6. False 

下面是最后一个例子,看完是不是觉得自己的脑子要爆炸?

  1. >>> a = 1000 
  2. >>> b = 1000 
  3. >>> a == b 
  4. True 
  5. >>> a is b 
  6. False 
  7. >>> a = b  
  8. >>> a == b 
  9. True 
  10. >>> a is b 
  11. True 

“ ==”的正式运算是相等,而“ is”的运算是标识。 一般使用“ ==”来比较两个对象的值。 “ a == b”应解释为“ a的值是否等于b的值”。 在上述所有示例中,a 的值始终等于 b 的值(即使对于空列表示例也是如此)。 因此,“ a == b”始终为真。

在解释身份之前,我需要先介绍 id 函数。 我们可以使用 id 函数获得对象的标识。 这个身份在整个时间内对于此对象都是唯一且恒定的。此标识在整个时间内对该对象是唯一且不变的。你可以把它看作是这个对象的地址。如果两个对象具有相同的标识,则它们的值也必须相同。

  1. >>> id(a) 
  2. 2047616 

运算符“ is ”是比较两个对象的标识是否相同。“a is b”的意思是“a的身份与b的身份相同”。

如果你知道“ ==”和“ is”的实际含义,我们就可以开始研究上面的几个示例了。

首先是第一个和第二个示例中的结果不同。 显示不同结果的原因是Python存储了一个介于-5到256之间的整数的数组列表,每个整数具有固定的标识。当我们在此范围内分配整数变量时,Python会将此变量的标识分配为数组列表内整数的整数。 结果,对于第一个示例,由于a和b的标识都是从数组列表中获得的,因此它们的标识当然是相同的,因此 “a is b” 为True。

  1. >>> a = 5 
  2. >>> id(a) 
  3. 1450375152 
  4. >>> b = 5 
  5. >>> id(b) 
  6. 1450375152 

但是一旦该变量的值超出该范围,由于 Python 内部没有具有该值的对象,因此Python将为此变量创建一个新的标识并将该值分配给该变量。 如前所述,身份对于每个创建都是唯一的,因此,即使两个变量的值相同,其身份也永远不会相等。 这就是为什么“a is b”在第二个例子结果为False。

  1. >>> a = 1000 
  2. >>> id(a) 
  3. 12728608 
  4. >>> b = 1000 
  5. >>> id(b) 
  6. 13620208 

PS:如果你打开了两个控制台,该值仍在该范围内,那么你将获得相同的标识。但是,如果该值不在该范围内,则结果就会发生改变。

 

“==”和“is”有什么区别?一个问题就能暴露你的Python水平

如果你理解了第一示例和第二示例之间的区别,就很容易理解第三示例的结果。由于 Python 不存储“空列表”对象,因此 Python 创建了一个新对象并分配了“空列表”值。无论两个列表为空还是元素相同,结果都是相同的。

  1. >>> a = [1,10,100,1000] 
  2. >>> b = [1,10,100,1000] 
  3. >>> a == b  
  4. True 
  5. >>> a is b 
  6. False 
  7. >>> id(a) 
  8. 12578024 
  9. >>> id(b) 
  10. 12578056 

接下来,我们转到最后一个示例。第二个和最后一个示例之间的唯一区别是还有一行代码 a = b,正是这行代码改变了变量 a 的命运。以下结果将告诉你真实原因:

  1. >>> a = 1000 
  2. >>> b = 2000 
  3. >>> id(a) 
  4. 2047616 
  5. >>> id(b) 
  6. 5034992 
  7. >>> a = b 
  8. >>> id(a) 
  9. 5034992 
  10. >>> id(b) 
  11. 5034992 
  12. >>> a 
  13. 2000 
  14. >>> b 
  15. 2000 

如上所示,在 a = b 之后,a 的身份更改为 b 的身份。a = b 将 b 的身份分配给 a 。因此 a 和 b 具有相同的标识,因此 a 的值现在与 b 的值相同(即2000)。

最后一个示例告诉我们一个重要消息,即我们可能会无意中更改对象的值,而不会事先通知,尤其是当对象是列表时。

  1. >>> a = [1,2,3] 
  2. >>> id(a) 
  3. 5237992 
  4. >>> b = a 
  5. >>> id(b) 
  6. 5237992 
  7. >>> a.append(4) 
  8. >>> a 
  9. [1, 2, 3, 4] 
  10. >>> b 
  11. [1, 2, 3, 4] 

在上面的示例中,由于 a 和 b 具有相同的标识,因此它们的值必须相同。 所以,在将新元素添加到 a 之后,b 的值也会受到影响。为避免这种情况,如果要将值从一个对象复制到另一个对象而不引用相同的标识,则所有方法之一是在 copy 模块中使用 deepcopy 。 对于列表,我们还可以通过 b = a [:] 执行。

  1. >>> import copy 
  2. >>> a = [1,2,3] 
  3. >>> b= copy.deepcopy(a) 
  4. >>> id(a) 
  5. 39785256 
  6. >>> id(b) 
  7. 5237992 

使用[:]将元素复制到新变量。

  1. >>> a = [1,2,3] 
  2. >>> id(a) 
  3. 39785256 
  4. >>> b = a[:] 
  5. >>> id(b) 
  6. 23850216 
  7. >>> a.append(4) 
  8. >>> a 
  9. [1, 2, 3, 4] 
  10. >>> b 
  11. [1, 2, 3] 

看完以上内容,你是不是已经充分了解了两者之间的不同?如果面试遇到这种问题,千万别回答错啦!

责任编辑:未丽燕 来源: 今日头条
相关推荐

2021-09-10 17:02:43

Python协程goroutine

2022-08-31 08:33:54

Bash操作系统Linux

2024-03-05 18:19:07

localhostLinux数据库

2020-03-09 20:56:19

LoRaLoRaWAN无线技术

2022-06-06 14:53:02

LoRaLoRaWAN

2022-09-08 18:38:26

LinuxWindowsmacOS

2020-11-09 14:07:53

PyQtQt编程

2022-09-07 18:32:57

并发编程线程

2022-08-02 08:23:37

SessionCookies

2021-12-17 14:40:02

while(1)for(;;)语言

2022-02-27 15:33:22

安全CASBSASE

2021-05-16 14:26:08

RPAIPACIO

2024-03-05 18:59:59

前端开发localhost

2023-11-01 08:08:47

PythonIS运算符

2018-07-20 14:00:51

LinuxmacOS内核

2023-10-27 15:31:04

For循环Foreach循环

2022-10-08 00:24:40

嵌套事务加入事务事务

2022-03-13 18:53:31

interfacetypeTypeScript

2023-12-15 09:21:17

ObjectJavaString

2022-08-22 07:06:32

MyBatisSQL占位符
点赞
收藏

51CTO技术栈公众号