Python中对象的比较操作==和is区别详析


Posted in Python onFebruary 12, 2021

前言

Python 中对象的比较有两种方式 == 和 is。两种方式都能判断操作符两侧的变量值是否相等,那么它们的区别是什么呢?通过下面的介绍我们来一探究竟。

比较操作符通常用于条件语句,如下示例:

if a == b:
 pass
if a is False:
 pass

== 与 is 的区别

== 操作符比较对象的值是否相等。小明有一块 劳力士 手表,小李也有一块同款 劳力士 手表,这时我们就认为这两块手表相等。

小明的手表 = 劳力士
小李的手表 = 劳力士
小明的手表 == 小李的手表

is 操作符比较对象的身份标识是否相等,即对象在内存中的地址是否相同,如果两个对象的身份标识相等,就说明它们是同一个对象。小明的爸爸称呼小明叫 儿子,小明的女朋友称呼小明叫 老公,但这两个称呼都代表 小明 这个人,即为同一个对象。

爸爸的儿子 = 小明
女朋友的老公 = 小明
爸爸的儿子 is 女朋友的老公

接下来就用代码来展示一下 == 与 is 的区别:

>>> a = [1, 2, 3]
>>> b = [1, 2, 3]
>>> a == b
True
>>> a is b
False
>>> id(a)
24603664
>>> id(b)
24603144
>>> a = [1, 2, 3]
>>> b = a
>>> a == b
True
>>> a is b
True
>>> id(a)
24604144
>>> id(b)
24604144

在 Python 中 id 函数接收一个对象作为参数,并返回该对象在内存中的地址。

由以上代码可以分析出:== 操作符只比较两个对象的值是否相等,但不比较两个对象是否为同一个对象;而 is 操作符并不是比较两个对象的值是否相等,而是会确认两个对象是否为同一个对象,如果为同一个对象,那么它们的值自然相等。

Python 小整数对象池

以上两段代码已经能够体现出 == 与 is 的区别,不过 Python 中也有一些特殊情况,来看下面例子:

>>> a = 5
>>> b = 5
>>> a == b
True
>>> a is b
True
>>> id(a)
1730274128
>>> id(b)
1730274128
>>> a = 257
>>> b = 257
>>> a == b
True
>>> a is b
False
>>> id(a)
48558688
>>> id(b)
48558720

以上代码看起来就很怪异了,同样的比较操作,只是换了一个数字结果就不同了。

其实出现以上结果的原因在于 Python 自身。Python 出于性能上的考虑,在解释器启动的时候就已经将 -5 到 256 的整数创建到内存中了。而当我们需要创建值在 -5 到 256 的 int 数字的时候,Python 并不会新开辟一块内存去创建数字,而是直接将已存在的对象返回。

但是如果新创建的数字不在这个范围,Python 就会为每个变量单独开辟自己的内存空间。

Python intern 机制

再来看下面关于字符串比较的例子:

>>> a = 'hello world'
>>> b = 'hello world'
>>> a == b
True
>>> a is b
False
>>> id(a)
49465408
>>> id(b)
49465448
>>> a = 'hello'
>>> b = 'hello'
>>> a == b
True
>>> a is b
True
>>> id(a)
49429152
>>> id(b)
49429152

想必根据之前数字比较的例子,你大概也能猜测到以上代码结果不同的原因了。事实上,以上结果同样是 Python 出于对性能的考虑,不过这次 Python 并没有预先将 hello 字符串创建到内存中,而是使用了一种叫 intern 的机制。

关于 intern 机制在这里我们不去深究,以后有机会专门写一篇博客来介绍。总之你需要知道在某些场景下,Python 会对字符串开启 intern 机制来提高性能,从而导致出现上面示例代码的结果。

== 与 is 各自的适用场景

什么时候用 ==、什么时候用 is 呢?

当我们需要比较一个变量与一个 单例 的时候,应该使用 is,其他情况通常使用 ==。

例如拿一个变量去跟 True 或 False 进行比较的时候就应该使用 is,因为用 is 的比较的速度要比用 == 更快。

用 is 比较对象的时候,只需要判断它们是否处于同一块内存地址即可,而用 == 比较更慢的原因在于当用 == 去比较对象的时候会调用对象的 __eq__() 方法,而 __eq__() 方法通常会被重载,执行其内部逻辑往往会多花一些时间。

以下就是一个重载对象 __eq__() 方法的例子:

class MyList(object):
  def __init__(self, *args):
    self._list = [*args]

  def __eq__(self, other):
    result = False
    for i in self._list:
      for j in other._list:
        if i == j:
          break
      else:
        break
    else:
      result = True
    return result

li_1 = MyList(1, 2, 3)
li_2 = MyList(1, 2, 3)
print(li_1 == li_2) # True

你可以自行尝试修改 __eq__() 方法内部的逻辑来观察其结果。

总结

到此这篇关于Python中对象的比较操作==和is的文章就介绍到这了,更多相关Python对象比较操作==和is内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python处理文本文件实现生成指定格式文件的方法
Jul 31 Python
Python 创建子进程模块subprocess详解
Apr 08 Python
查看Python安装路径以及安装包路径小技巧
Apr 28 Python
python基于urllib实现按照百度音乐分类下载mp3的方法
May 25 Python
python函数局部变量用法实例分析
Aug 04 Python
python如何使用正则表达式的前向、后向搜索及前向搜索否定模式详解
Nov 08 Python
Python实现确认字符串是否包含指定字符串的实例
May 02 Python
Django分页查询并返回jsons数据(中文乱码解决方法)
Aug 02 Python
python求质数的3种方法
Sep 28 Python
pandas计数 value_counts()的使用
Jun 24 Python
python GUI库图形界面开发之PyQt5菜单栏控件QMenuBar的详细使用方法与实例
Feb 28 Python
使用OpenCV实现道路车辆计数的使用方法
Jul 15 Python
python绘图模块之利用turtle画图
Feb 12 #Python
Python列表的深复制和浅复制示例详解
Feb 12 #Python
Python就将所有的英文单词首字母变成大写
Feb 12 #Python
详解Java中一维、二维数组在内存中的结构
Feb 11 #Python
SpringBoot首页设置解析(推荐)
Feb 11 #Python
使用Python爬取小姐姐图片(beautifulsoup法)
Feb 11 #Python
详解python日志输出使用配置文件格式
Feb 10 #Python
You might like
PHP5.3的垃圾回收机制(动态存储分配方案)深入理解
2012/12/10 PHP
解析VS2010利用VS.PHP插件调试PHP的方法
2013/07/19 PHP
PHP实现简单实用的分页类代码
2016/04/08 PHP
PHP基于socket实现客户端和服务端通讯功能
2017/07/13 PHP
PHP使用正则表达式实现过滤非法字符串功能示例
2018/06/04 PHP
javascript下操作css的float属性的特殊写法
2007/08/22 Javascript
jQuery弹出层插件简化版代码下载
2008/10/16 Javascript
Linux下编译安装php libevent扩展实例
2015/02/14 Javascript
javascript中mouseover、mouseout使用详解
2015/07/19 Javascript
chrome调试javascript详解
2015/10/21 Javascript
Document.body.scrollTop的值总为零的快速解决办法
2016/06/09 Javascript
JS使用遮罩实现点击某区域以外时弹窗的弹出与关闭功能示例
2018/07/31 Javascript
layui实现form表单同时提交数据和文件的代码
2019/10/25 Javascript
微信公众号H5之微信分享常见错误和问题(小结)
2019/11/14 Javascript
python实现udp数据报传输的方法
2014/09/26 Python
python 按照固定长度分割字符串的方法小结
2018/04/30 Python
Python实现提取XML内容并保存到Excel中的方法
2018/09/01 Python
python批量下载网站马拉松照片的完整步骤
2018/12/05 Python
对Python3 序列解包详解
2019/02/16 Python
python numpy 矩阵堆叠实例
2020/01/17 Python
Python中if有多个条件处理方法
2020/02/26 Python
Python 如何反方向迭代一个序列
2020/07/28 Python
python 自定义异常和主动抛出异常(raise)的操作
2020/12/11 Python
python time.strptime格式化实例详解
2021/02/03 Python
使用css创建三角形 使用CSS3创建3d四面体原理及代码(html5实践)
2013/01/06 HTML / CSS
h5使用canvas画布实现手势解锁
2019/01/04 HTML / CSS
Waterford英国官方网站:世界上最受欢迎的优质水晶品牌
2019/08/17 全球购物
医学专业毕业生个人的求职信
2013/12/04 职场文书
模范班主任事迹材料
2014/12/17 职场文书
2014年小学语文工作总结
2014/12/20 职场文书
小学五年级语文上册教学计划
2015/01/22 职场文书
校长个人总结
2015/03/03 职场文书
2015年社区计生工作总结
2015/04/21 职场文书
2015年保洁工作总结范文
2015/04/28 职场文书
遗嘱范文
2015/08/07 职场文书
css中z-index: 0和z-index: auto的区别
2021/08/23 HTML / CSS