认清Python下==和is的区别
通常在Python语言中我们判断两个字符串是否相等的时候,很多同学在初学Python的时候会混用==
和is
,最后造成的结果就是出错的时候不知道怎么定位,结果也让自己意想不到。
下面我们先来看一下==
和is
的表现:
>>> a = 'hello'
>>> b = 'hello'
>>> a is b
True
>>> a == b
True
>>> # 如上情况 is 和 == 的结果一致>>> a1 = "I'm a long string for code testing"
>>> b1 = "I'm a long string for code testing"
>>> a1 is b1
False
>>> a1 == b1
True
>>> # 如上情况 is 和 == 结果不一致>>> str1 = "string"
>>> str2 = "".join(['s', 't', 'r', 'i', 'n', 'g'])
>>> str2
'string'
>>> str1 is str2
False
>>> str1 == str2
True
>>> # 如上情况 is 和 == 结果不一致
为什么会出现这种情况呢?为什么在有些情况下is
和==
输出结果相同有些情况又不同呢?我们简单做如下分析: 首先通过id()
函数来看看这些变量在内存中的具体存储空间,整理情况如下:
从上图表格中我们可以看出来is
和==
在验证两个字符串是否相等的时候表现是不一致的,显然如果你混用或者误认为他们是等同的那是存在风险的。
那么字符串的比较到底是用is
还是==
呢,我们来看一下Python官方文档中对两种操作的说明:
Operation |
Syntax |
Function |
---|---|---|
Identity |
a is b |
is_(a, b) |
Equality |
a == b |
eq(a, b) |
从上可知is
表示的是标识符(Identity),而==
表示的意思是相等(Equality),显然两者不是一个东西。
实际上造成上面输出结果不一致的根本原因在于is
的作用在于用来检查对象的标识符是否一致,也就是说is
是比较两个对象在内存中是否拥有同一块内存空间,它并不适合来判断两个字符串是否相等。a is b
仅当a和b是同一个对象的时候才返回True, 所以a is b
基本上相当于id(a) == id(b)。
而==
才是真正用来判断两个对象的值是否相等的,它实际调用的是builtins.py
中的__eq__()
方法,因此a == b
相当于a.__eq__()b
, 所以 ==
操作符可以被重载,而 is
是不能被重载的。
一般情况下如果a is b
为True的话a == b
的值也是True,反之则亦然。 特殊情况除外,如下所示:
>>> a = float('NaN')
>>> a is a
True
>>> a == a
False
从上面的介绍弄清楚了is
和==
的区别之后,我们再来看图示表格中的输出就不难理解了。细心点的同学可能会发现,在表格中a和b的id值一样,也就是说他们在同一内存空间地址中,而a1和b1的id值却不一样,这是为什么呢?这是因为Python中string interning(字符串驻留)
机制所决定的: 相对于较小的字符串,Python为了提高性能会保留其值的一个副本,当你再次创建这个字符串的时候,直接就指向了这个副本,所以'hello'这个字符串是在内存中有一个副本的,所以a和b的id的值是一样的;而a1和b1是长字符串,并不会驻留,Python在内存中分别为a1和b1创建了一个内存对象来标识a1和b1,所以这两个对象拥有相同的内容但是标识符是不一样的,所以==
的值为True而is
的值为False。
所以最后总结一下,在Python里面你要判断两个对象是否相等你应该使用==
而不是is。
- Modbus RTU驱动程序开发指引
- freeRTOS任务创建
- 洛谷P4213 Sum(杜教筛)
- JVM活学活用——调优工具
- .Net中的AOP系列之构建一个汽车租赁应用(下)
- Zookeeper学习笔记——2 Shell和Java API的使用
- Java基础巩固——反射
- 手把手教你在树莓派上搭建web服务器
- 安装和搭建基于netcore的demo
- 项目心得:广度遍历搜索部门处理业务
- 使用JAVA开发微信公众平台(一)——环境搭建与开发接入
- BZOJ4805: 欧拉函数求和(杜教筛)
- centos7.x下搭建netcore环境和helloworld的demo
- ARM coretex M4 系统定时器
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- UidGenerator:百度开源的分布式ID服务(解决了时钟回拨问题)
- String及StringTable(四):StringBuffer与StringBuilder对比
- Apache James 2.3.2.1 邮箱服务搭建
- SpringBoot实现微信小程序登录的完整例子
- String及StringTable(五):java8的新工具类StringJoiner
- spring security oauth2使用refresh_token报错UserDetailsService is required
- 你所不知道的React| 趋势解读、底层逻辑、学习路径、实战应用
- js中setTimeout的用法和JS计时器setTimeout与setInterval方法的区别和confirm方法
- TKinter Label 和 Button
- Java类如何防止被实例化
- PHP中的json_encode和json_decode
- Java重写equals和hashCode方法
- upload-labs第11~12关 00截断
- java 踩雷日记--new
- 用一个通俗易懂的例子彻底说清楚单例模式