Python菜鸟教程:is 和 == 区别,如何判断两个对象是否相同?

2023-03-2909:17:49编程语言入门到精通Comments945 views字数 1942阅读模式
Python菜鸟教程:is 和 == 区别,如何判断两个对象是否相同?
作者:咸鱼Linux运维

is 和 == 的区别

相信学过 Python 小伙伴们都知道 is 和 == 都是用来比较 Python 对象的,但是区别就是:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

  • is 比较需要对象的值和内存地址都相等
  • == 比较只需要对象的值相等就行了

我们来看一个例子文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

Python菜鸟教程:is 和 == 区别,如何判断两个对象是否相同?
Python菜鸟教程:is 和 == 区别,如何判断两个对象是否相同?

我们可以看到,time 模块的 time() 方法用于获取当前时间,所以 t1 和 t2 的值都是一样的文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

== 用来判断 t1 和 t2 的值是否相等,所以返回 True文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

虽然 t1 和 t2 的值相等,但它们是两个不同的对象(每次调用 time() 都返回不同的对象),所以t1 is t2返回 False文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

那么,如何判断两个对象是否相同呢?文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

答:判断两个对象的内存地址。如果内存地址相同,说明两个对象使用的是同一块内存,当然就是同一个对象了文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

我们来看下 t1 和 t2 的内存地址文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

Python菜鸟教程:is 和 == 区别,如何判断两个对象是否相同?
Python菜鸟教程:is 和 == 区别,如何判断两个对象是否相同?

可以看到它们两个的内存地址是不一样的文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

Python菜鸟教程:is 和 == 区别,如何判断两个对象是否相同?

小整数池&缓存机制

但是有小伙伴可能会遇到下面的这种情况文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

Python菜鸟教程:is 和 == 区别,如何判断两个对象是否相同?

咦?怎么 a is b 结果是 True?这应该是两个不同的对象啊文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

这其实是因为小整数池文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

python 中经常使用的一些数值定义为小整数池,小整数池的范围是[-5,256]文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

python 对这些数值已经提前创建好了内存空间,即使多次重新定义也不会再重新开辟新的空间,但是小整数池外的数值在重新定义时都会再次开辟新的空间文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

所以对于小整数池中的数,内存地址一定是相同的,小整数池中外的数,内存地址是不同的文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

Python菜鸟教程:is 和 == 区别,如何判断两个对象是否相同?

好,那这次我用小整数池之外的数文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

Python菜鸟教程:is 和 == 区别,如何判断两个对象是否相同?
Python菜鸟教程:is 和 == 区别,如何判断两个对象是否相同?
Python菜鸟教程:is 和 == 区别,如何判断两个对象是否相同?

?玩我是吧,说好的小整数池中外的数,内存地址是不同的,那上面的代码结果怎么跟说的不一样文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

上面的代码我是在 IDE 环境下面敲的,我们试着在交互模式下敲文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

Python菜鸟教程:is 和 == 区别,如何判断两个对象是否相同?
Python菜鸟教程:is 和 == 区别,如何判断两个对象是否相同?

可以看到,在交互模式下,小整数池外的数内存地址不相同,这是为什么呢?文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

先说结论:这是因为 Python 的缓存机制,所以在 IDE 环境或者脚本模式下同一个整数被多个变量引用不会开辟新的内存空间文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

Python菜鸟教程:is 和 == 区别,如何判断两个对象是否相同?

Python 缓存机制

  • Python 解释器启动时会先从内存空间中开辟出来一小部分,用于存储高频使用的数据(不可变数据类型),这样可以大大减少高频使用的数据对象创建时申请内存和销毁时撤销内存的开销
  • 在同一代码块下,不可变数据类型的对象(数字,字符串,元祖)被多个变量引用,不会重复开辟内存空间

由上面得知,只有不可变的数据类型(字符串、元祖、基础数据类型)如果被多个变量引用,是不会重复开辟内存空间,但可变数据类型(列表、字典、集合)就除外文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

  • 可变数据类型

我们来看看文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

Python菜鸟教程:is 和 == 区别,如何判断两个对象是否相同?
Python菜鸟教程:is 和 == 区别,如何判断两个对象是否相同?
Python菜鸟教程:is 和 == 区别,如何判断两个对象是否相同?

在交互模式下结果也是如此文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

Python菜鸟教程:is 和 == 区别,如何判断两个对象是否相同?
  • 不可变数据类型

1、小整数池里的数文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

我们来看下交互模式下的不可变数据类型的缓存机制文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

Python菜鸟教程:is 和 == 区别,如何判断两个对象是否相同?

可以看到,Python 中整数范围 [-5, 256] 中的数为固定缓存,只要是使用到该范围内的数字,不管是直接赋值还是表达式计算得到的,都会使用固定缓存中的数据文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

2、非小整数池里的数文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

对于非小整数池里的数,在 IDE 环境下会使用到缓存,即多个变量引用同一个数据,不会开辟新的内存空间文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

Python菜鸟教程:is 和 == 区别,如何判断两个对象是否相同?

对于非小整数池里的数,在交互模式下,除非同时赋值或者在同一个局域代码块里面赋值,否则不会使用缓存机制文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

Python菜鸟教程:is 和 == 区别,如何判断两个对象是否相同?
Python菜鸟教程:is 和 == 区别,如何判断两个对象是否相同?

intern 机制

我们知道,由于 Python 的缓存机制:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

  • 不可变的数据类型(字符串、元祖、基础数据类型)如果被多个变量引用,是不会重复开辟内存空间
  • 但可变数据类型(列表、字典、集合)被多个变量引用就会开辟新的内存空间
  • 对于小整数池里的整数,被多个变量引用,不会重复开辟内存空间

但是到目前为止我们知道:在交互模式下,除了特殊情况(同时赋值、同一局域代码块内赋值)以及小整数池之外,所有数据在被多个变量引用时都会开辟新的内存空间文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

其实还有一种特殊情况,我们来看这么一个例子文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

Python菜鸟教程:is 和 == 区别,如何判断两个对象是否相同?

看着输出的结果,再跟刚刚所学到的知识做一下对比,是不是发现有不对劲的地方文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

交互模式下,多个变量引用字符串(不可变数据类型)应该是开辟新的内存空间啊,为啥上面的例子没有开辟文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

intern机制文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

字符串类型作为Python中最常用的数据类型之一,Python 为了提高字符串使用的效率和使用性能,使用了 intern(字符串驻留)的技术来提高字符串效率文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

即值同样的字符串对象仅仅会保存一份,放在一个字符串储蓄池中,是共用的,有新的变量引用同样的字符串的时候,不会开辟新的内存空间,而是引用这个共用的字符串文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

  • 原理

实现 Intern 机制的方式非常简单,就是通过维护一个字符串储蓄池,这个池子是一个字典结构,如果字符串已经存在于池子中就不再去创建新的字符串,直接返回之前创建好的字符串对象,如果之前还没有加入到该池子中,则先构造一个字符串对象,并把这个对象加入到池子中去,方便下一次获取文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

下面是伪代码文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

Python菜鸟教程:is 和 == 区别,如何判断两个对象是否相同?

1、在交互模式下,只包含字母数字下划线的字符串才会触发 intern 机制文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

Python菜鸟教程:is 和 == 区别,如何判断两个对象是否相同?
Python菜鸟教程:is 和 == 区别,如何判断两个对象是否相同?

2、在 IDE 环境或者脚本模式下,只要长度不超过20(长度限制),即使使用特殊字符也会触发 intern 机制文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

Python菜鸟教程:is 和 == 区别,如何判断两个对象是否相同?
Python菜鸟教程:is 和 == 区别,如何判断两个对象是否相同?

PS:我在写这篇文章的时候用的是 python 3.9,发现没有长度限制了,都会触发 intern 机制文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html

Python菜鸟教程:is 和 == 区别,如何判断两个对象是否相同?
文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/32592.html
  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/ymba/32592.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定