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判断端口是否打开的实现代码
Feb 10 Python
python脚本实现分析dns日志并对受访域名排行
Sep 18 Python
初步理解Python进程的信号通讯
Apr 09 Python
python开发环境PyScripter中文乱码问题解决方案
Sep 11 Python
详解python中xlrd包的安装与处理Excel表格
Dec 16 Python
详解python字节码
Feb 07 Python
使用pandas read_table读取csv文件的方法
Jul 04 Python
使用python实现快速搭建简易的FTP服务器
Sep 12 Python
Python内置函数property()如何使用
Sep 01 Python
怎么解决pycharm license Acti的方法
Oct 28 Python
Python集合set()使用的方法详解
Mar 18 Python
Python数组变形的几种实现方法
May 30 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
php Http_Template_IT类库进行模板替换
2009/03/19 PHP
php如何获取文件的扩展名
2015/10/28 PHP
PHP数组函数知识汇总
2016/05/12 PHP
PHP开发APP端微信支付功能
2017/02/17 PHP
ThinkPHP实现附件上传功能
2017/04/27 PHP
PHP十六进制颜色随机生成器功能示例
2017/07/24 PHP
Laravel 创建指定表 migrate的例子
2019/10/09 PHP
Javascript与flash交互通信基础教程
2008/08/07 Javascript
web前端设计师们常用的jQuery特效插件汇总
2014/12/07 Javascript
node.js中的http.response.write方法使用说明
2014/12/14 Javascript
JavaScript插件化开发教程(五)
2015/02/01 Javascript
AngularJS监听路由的变化示例代码
2016/09/23 Javascript
微信小程序 自定义对话框实例详解
2017/01/20 Javascript
Javascript前端经典的面试题及答案
2017/03/14 Javascript
vue增删改查的简单操作
2017/07/15 Javascript
JS中DOM元素的attribute与property属性示例详解
2018/09/04 Javascript
Vue.js 中的 v-show 指令及用法详解
2018/11/19 Javascript
微信小程序新手教程之页面打开数量限制
2019/03/03 Javascript
django 自定义用户user模型的三种方法
2014/11/18 Python
windows下python安装pip图文教程
2018/05/25 Python
python实现批量解析邮件并下载附件
2018/06/19 Python
python的常用模块之collections模块详解
2018/12/06 Python
Pandas DataFrame数据的更改、插入新增的列和行的方法
2019/06/25 Python
pytorch 实现cross entropy损失函数计算方式
2020/01/02 Python
Python视频编辑库MoviePy的使用
2020/04/01 Python
python进行OpenCV实战之画图(直线、矩形、圆形)
2020/08/27 Python
python 动态渲染 mysql 配置文件的示例
2020/11/20 Python
Tech21美国/加拿大:英国NO.1防摔保护壳品牌
2018/01/20 全球购物
什么是托管函数?托管函数有什么用?
2014/06/15 面试题
软件测试企业面试试卷
2016/07/13 面试题
应届大学毕业生找工作的求职信范文
2013/11/29 职场文书
工作失误检讨书(经典集锦版)
2014/10/17 职场文书
2015年学校消防安全工作总结
2015/10/14 职场文书
大学班干部竞选稿
2015/11/20 职场文书
导游词之河北野三坡
2019/12/11 职场文书
Nginx解决前端访问资源跨域问题的方法详解
2021/03/31 Servers