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脚本实现格式化css文件
Apr 08 Python
Python实现将SQLite中的数据直接输出为CVS的方法示例
Jul 13 Python
Python网络爬虫中的同步与异步示例详解
Feb 03 Python
Python系统监控模块psutil功能与经典用法分析
May 24 Python
Python 中的range(),以及列表切片方法
Jul 02 Python
python中使用print输出中文的方法
Jul 16 Python
Anaconda下配置python+opencv+contribx的实例讲解
Aug 06 Python
分享8个非常流行的 Python 可视化工具包
Jun 05 Python
Python 中的参数传递、返回值、浅拷贝、深拷贝
Jun 25 Python
Django中如何使用sass的方法步骤
Jul 09 Python
python实现加密的方式总结
Jan 19 Python
详解pyqt5的UI中嵌入matplotlib图形并实时刷新(挖坑和填坑)
Aug 07 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 Session生命周期介绍
2010/03/02 PHP
php中使用addslashes函数报错问题的解决方法
2013/02/06 PHP
PHP与javascript实现变量交互的示例代码
2013/07/23 PHP
JS对象转换为Jquery对象示例
2014/01/26 Javascript
node.js中的fs.readFile方法使用说明
2014/12/15 Javascript
JavaScript实现数据类型的相互转换
2016/03/06 Javascript
基于JS实现数字+字母+中文的混合排序方法
2016/06/06 Javascript
AngularJS 执行流程详细介绍
2016/08/18 Javascript
老生常谈原生JS执行环境与作用域
2016/11/22 Javascript
Jquery Easyui分割按钮组件SplitButton使用详解(17)
2016/12/18 Javascript
react系列从零开始_简单谈谈react
2017/07/06 Javascript
React-Native实现ListView组件之上拉刷新实例(iOS和Android通用)
2017/07/11 Javascript
Angularjs上传文件组件flowjs功能
2017/08/07 Javascript
vue.js内置组件之keep-alive组件使用
2018/07/10 Javascript
vue组件化中slot的基本使用方法
2019/05/01 Javascript
深度了解vue.js中hooks的相关知识
2019/06/14 Javascript
vue设置一开始进入的页面教程
2019/10/28 Javascript
微信小程序点击view动态添加样式过程解析
2020/01/21 Javascript
Python中list列表的一些进阶使用方法介绍
2015/08/15 Python
通过Python 接口使用OpenCV的方法
2018/04/02 Python
pandas将numpy数组写入到csv的实例
2018/07/04 Python
Python OpenCV 调用摄像头并截图保存功能的实现代码
2019/07/02 Python
Python爬虫运用正则表达式的方法和优缺点
2019/08/25 Python
django修改models重建数据库的操作
2020/03/31 Python
Django ORM 查询表中某列字段值的方法
2020/04/30 Python
HTML5本地存储和本地数据库实例详解
2017/09/05 HTML / CSS
Avène雅漾美国官方网站:敏感肌肤护理专家
2016/10/24 全球购物
Lampegiganten丹麦:欧洲领先的照明网上商店
2018/04/25 全球购物
RIP版本1跟版本2的区别
2013/12/30 面试题
《乞巧》教学反思
2014/02/27 职场文书
读书活动实施方案
2014/03/10 职场文书
某某同志考察材料
2014/05/28 职场文书
消防工作实施方案
2014/06/09 职场文书
工伤事故赔偿协议书范文
2014/09/24 职场文书
学习心理学的体会
2014/11/07 职场文书
nginx服务器的下载安装与使用详解
2021/08/02 Servers