0 前言

Python中有很多运算符,今天我们就来讲讲is和==两种运算符在应用上的本质区别是什么。

在讲is和==这两种运算符区别之前,首先要知道Python中对象包含的三个基本要素,分别是:id(身份标识)、type(数据类型)和value(值)。

is和==都是对对象进行比较判断作用的,但对对象比较判断的内容并不相同。下面来看看具体区别在哪。
注: 文中的例子如无特殊说明,都是在python3中测试的

1 ==比较操作符和is同一性运算符区别

==表示两个对象是否相等,相当于调用__eq__()方法,即’a==b’ ==> a.eq(b)。
is表示的是对象标识符,用来检查对象的标识符是否一致,即两个对象在内存中的地址是否一致。在使用 a is b 的时候,相当于id(a)==id(b)。
==是python标准操作符中的比较操作符,用来比较判断两个对象的value(值)是否相等,例如下面两个字符串间的比较:

>>> a = 'cheesezh'
>>> b = 'cheesezh'
>>> a == b
True

is也被叫做同一性运算符,这个运算符比较判断的是对象间的唯一身份标识,也就是id是否相同。 通过对下面几个list间的比较,你就会明白is同一性运算符的工作原理:
list间的比较

>>> x = y = [4,5,6]
>>> z = [4,5,6]
>>> x == y
True
>>> x == z
True
>>> x is y
True
>>> x is z
False
>>>
>>> print id(x)
3075326572
>>> print id(y)
3075326572
>>> print id(z)
3075328140

可以看到,前三个比较都是True,最后一个 x is z 是False,x、y和z的值是相同的,所以前两个是True没有问题。至于最后一个为什么是False,看看三个对象的id分别是什么就会明白了。x和y指向同一个对象,x和z指向不同的对象。

2 int 和str类型

下面再来看一个例子,看看int和str类型的==和is的区别

#整型
>>> a = 1 #a和b为数值类型
>>> b = 1
>>> a is b
True
>>> a == b #可以看到,可以直接使用==判断,集合的值是不是相等,只有集合所有的值相等时集合才相等
True
>>> id(a)
1526754368
>>> id(b)
1526754368
>>> a = a + 1
>>> c = 2
>>> a is c
True
>>> a == c
True
>>> id(a)
1526310032
>>> id(b)
1526310032#字符串
>>> a = 'cheesezh' #a和b为字符串类型
>>> b = 'cheesezh'
>>> type(a)
<class 'str'>
>>> a is b
True
>>> a == b
True
>>> id(a)
2213691256560
>>> id(b)
2213691256560

可以看到,如果是int或者str类型的对象,值相等的对象(python一切皆对象),id也相等,所以如果==为True的话,使用is判断也是True。

3 tuple、list、dict和set类型

下面看一下集合类型的,==和is有什么区别:

#tuple
>>> a = (1,2,3) #a和b为元组类型
>>> b = (1,2,3)
>>> a==b
True
>>> a is b
False
>>> id(a)
42529704
>>> id(b)
47113056# list
>>> a = [1,2,3] #a和b为list类型
>>> b = [1,2,3]
>>> a==b
True
>>> a is b
False
>>> id(a)
49865160
>>> id(b)
49892872#dict
>>> a = {'cheese':1,'zh':2} #a和b为dict类型
>>> b = {'cheese':1,'zh':2}
>>> a==b #dict的key和value都相等的话,说明他们的值是相等的
True
>>> a is b
False
>>> id(a)
56599416
>>> id(b)
58167912#set
>>> a = set([1,2,3])#a和b为set类型
>>> b = set([1,2,3])
>>> a==b
True
>>> a is b
False
>>> id(a)
55617576
>>> id(b)
55793032

通过这个例子可以看到,虽然tuple,list,dict,或set的值相等,使用==返回的True,但是他们的id是不同的,使用is返回的是False。

4 bool类型的True和False

如果对象是bool类型的,判断对象是False还是True应该用==还是is呢,下面我们还是举个例子:

>>> type(True)
<class 'bool'>
>>> type(False)
<class 'bool'>>>> a = 1
>>> b = 1
>>> result = (a == b)
>>> type(result)
<class 'bool'>>>> result == True
True
>>> result is True
True
>>> id(result)
1526263968
>>> id(True)
1526263968

通过上面的例子可以看到:

  1. True和False是python的两个内建的对象,类型是bool
  2. (a==b)并没有生成新的bool对象,而是使result指向了True指向的对象,因为他们的Id相同,可见除了True和False,python并不会创建其他的bool对象。如果参考单例模式的,我们可不可以称这种限制为双例模式,除了这两个对象不能创建其他的对象。 即使我们使用了bool()函数创建了一个bool对象,它还是和True或者Flalse指向相同的内存, 通过下面的例子可以看到a和False的id相同:
>>> a = bool()
>>> False
>>> id(a)
1522515272
>>> id(False)
1522515272
  1. 判断result是不是True使用==和is都是可以的,这和int,str类型是一样的

推展: 上面的例子是python3的,其实在python中有一个有意思的现象就是,我们可以这样交换True和False对象的值,True,False = False,True, 比如下面的例子:

print(True)
print(False)
True,False = False,True
print(True)
print(False)
True
False
1522515688
1522515272
False
True
1522515272
1522515688

由上面的例子我们可以发现,print(True)输出True,print(False)输出False;交换之后print(True)输出False,print(True)输出False;并且True的地址也变成了False的地址。
上面的实验充分说明了,True和False 是一个对象,默认情况下True指向值为True的对象,交换后True就指向了值为False的对象。
不过在Python3中这种交换已经别禁止了。

5 为什么我们要用is None

好像我们来看None在python是一个怎样的存在:

  1. None有自己的数据类型NontType,你可以将None赋值给任意对象,但是不能创建一个NoneType对象。
>>> type(None)
<class 'NoneType'>
>>> n=NoneType()
Traceback (most recent call last):File "<input>", line 1, in <module>
NameError: name 'NoneType' is not defined
  1. None是python中的一个特殊的常量,表示一个空的对象,空值是python中的一个特殊值。数据为空并不代表是空对象,例如[],’'等都不是None。None和任何对象比较返回值都是False,除了自己。
>>> L=[]
>>> L is None
False
>>> L=''
>>> L is None
False

下面会到我们的问题,为什么要用is None?

因为None在Python里是个单例对象,一个变量如果是None,它一定和None指向同一个内存地址。

>>> a=None
>>> b=None
>>> id(a)==id(b)
True
>>> id(None)
1522470008
>>> id(a)
1522470008
>>> a == None
True
>>> a is None
True

is None是判断两个对象在内存中的地址是否一致,== None背后调用的是eq,而eq可以被重载,下面是一个 is not None但 == None的例子:

>>> class test():
...     def __eq__(self,other):
...         return True
...
>>> t=test()
>>> t is None
False
>>> t == None
True

关于None,就算你知道了应该使用is 来判断是否为None还有另一个坑,就是这个判断怎么写的问题,这个坑会用到这篇博客Python中的True和False与bool()函数吗?中的一些知识,不懂的话,可以去参考这篇博客,下面我们来看一下这个坑有多深。
在python中 None, False, 空字符串"", 0, 空列表[], 空字典{}, 空元组()都相当于False ,即:

not None == not False == not '' == not 0 == not [] == not {} == not ()

因此在使用列表的时候,如果你想区分x==[]和x==None两种情况的话, 此时if not x:将会出现问题:

>>> x = []
>>> y = None
>>>
>>> x is None
False
>>> y is None
True
>>> not x
True
>>> not y
True
>>> not x is None #相当于not (x is None)
>>> True
>>> not y is None
False

如果not x 你是想判断x是否为None,但是这样写会把x==[]的情况也包含进来了,这么无法区分两种情况。下面的not x is None是正确的,却不是很好理解,其意思是not (x is None), 最好的写法是 if x is not None,即清晰又不会出现问题。
所以在使用if not x的时候,一定要考虑清楚,必须清楚x等于None, False, 空字符串"", 0, 空列表[], 空字典{}, 空元组()时对你的判断没有影响才行。

结论

可以看到,python语言的语法虽然很简单,但是由于太灵活,语法和类型的检查不严格,写程序的时候不注意很容易出现问题。

原文链接:

  1. Python中is和==的区别
  2. python 中None,is和==的深入探讨
  3. python 判断变量是否是 None 的三种写法

Python中is和==的区别以及is None相关推荐

  1. 列举至少五个python内置函数和使用方法_Python内置函数 next的具体使用方法 Python中seek和next区别...

    python列表本来没有next方法,为什么用iter函数生...对list用__dir__()发现没有next方法,但是用iter()生成迭代器,对该迭代next是进行迭代的方法,只有迭代器和生成器 ...

  2. python中arg,*arg,**kwarg区别

    python中arg,*arg,**kwarg区别 1. *args(*的作用很重要) 首先要搞清楚*的意思和作用,有助于理解arg,*arg,**kwarg. (*是arg的前半部分,arg是后半部 ...

  3. Python中“is”和“==”的区别

    Python有两个用于相等比较的运算符,"is"和"=="(等于).在这篇文章中,我将教你们两者之间的区别,以及通过几个简单地例子说明什么时候使用它们. 当我还 ...

  4. pythonis啥意思-Python中is和==的区别

    Python中有很多运算符,今天我们就来讲讲is和==两种运算符在应用上的本质区别是什么. 在讲is和==这两种运算符区别之前,首先要知道Python中对象包含的三个基本要素,分别是:id(身份标识) ...

  5. Python中is和==的区别

    在Python中一切都是对象. Python中对象包含的三个基本要素,分别是:id(身份标识).type(数据类型)和value(值).对象之间比较是否相等可以用==,也可以用is. is和==都是对 ...

  6. python中str和int区别_python中eval与int的区别浅析

    python中eval和int的区别是什么?下面给大家介绍一下: 1.eval()函数 eval(<字符串>)能够以Python表达式的方式解析并执行字符串,并将返回结果输出.eval() ...

  7. python中sort和sorted区别_Python中的 sort 和 sorted的用法与区别

    今天在做一道题时,因为忘了Python中sort和sorted的用法与区别导致程序一直报错,找了好久才知道是使用方法错误的问题!现在就大致的归纳一下sort和sorted的用法与区别 1. sort: ...

  8. [转载] python中*args 和 **kwargs区别

    参考链接: 带有* args和** kwargs的Python中的可变长度参数 1 *args 和 **kwargs 定义. 你可以将不定数量的参数传递给一个函数.不定的意思是:预先并不知道, 函数使 ...

  9. python中*args 和 **kwargs区别

    1 *args 和 **kwargs 定义. 你可以将不定数量的参数传递给一个函数.不定的意思是:预先并不知道, 函数使用者会传递多少个参数给你, 所以在这个场景下使用这两个关键字.其实并不是必须写成 ...

最新文章

  1. Mysql for Mac 安装及环境配置
  2. html文件显示不了box,Workbox.js registerNavigationRoute找不到/加载html文件
  3. 【CURL】模拟登录网站并获取用户信息
  4. java merge json出错删除相同的json
  5. Win7性能信息和工具在哪打开
  6. 自然语言处理简介及开发环境
  7. rpm打包的流程包括以下哪些_Linux 下RPM打包制作流程
  8. bzoj 1042 HAOI2008 硬币购物
  9. sql server表分区_SQL Server中的FORCESCAN和分区表
  10. spring、mybatis、测试用例执行后数据没有入库
  11. 接收机IQ不平衡:估计和纠正 (Rx IQ imbalance: Estimation and Correction)
  12. curl 断点下载 wget下载
  13. C语言把csv文件转xls,Excel怎么批量将CSV格式转换为xlsx或xls格式?VBA、宏、软件?...
  14. 无损数据压缩算法c语言,C语言实现无损压缩算法
  15. android 锁屏 浮动窗口,Android如何实现锁屏状态下弹窗
  16. java数组显示_Java 1.5中显示数组
  17. RHCSA 2022/10/14
  18. Python高效实现滑块验证码自动操纵
  19. SCADA(Supervisory Control And Data Acquisition)系统, 数据采集与监视控制系统
  20. 自制钟表(用canvas)

热门文章

  1. html 随机画圈 不重叠,html实现随机图片
  2. 实现教材算法7.2利用邻接矩阵构造无向图的算法,在此基础上进行深度优先遍历和广度优先遍历。
  3. vcs与verdi学习记录
  4. 【深度学习】ToMe:我的方法无需训练即可加速 ViT 模型|搞懂Transformer系列
  5. 一起学画图:散点图+边缘分布统计图形-密度图-直方图-箱型图-小提琴图
  6. 专访吴恩达:加入百度一切比预想的要快
  7. 如何不解锁BL刷入Android 12/安卓程序员预览版或者刷回Android 11
  8. windows下简易安装ncl
  9. 摸鱼的小贤在瞎搞Python - Anaconda的安装
  10. 单片机中几种常用数据类型 bit,sbit,sfr,sfr16。