Python 中的比较:is 与 ==

 

在 Python 中会用到对象之间比较,可以用 ==,也可以用 is 。但是它们的区别是什么呢?

  • is 比较的是两个实例对象是不是完全相同,它们是不是同一个对象,占用的内存地址是否相同。莱布尼茨说过:“世界上没有两片完全相同的叶子”,这个is正是这样的比较,比较是不是同一片叶子(即比较的id是否相同,这id类似于人的身份证标识)。

  • == 比较的是两个对象的内容是否相等,即内存地址可以不一样,内容一样就可以了。这里比较的并非是同一片叶子,可能叶子的种类或者脉络相同就可以了。默认会调用对象的 __eq__()方法。

可以通过如下例子来区分比较下:

>>> a = ["I", "love", "Python"]
>>> b = a
# a的引用复制给b,在内存中其实是指向了用一个对象
>>> b is a
True
>>> id(a)
46381384
>>> id(b)
46381384
# 当然,内容也肯定是相等的
>>> b == a
True

可以发现b和a的内存地址是相同的,它们指向同一块内存,因而 is 和 == 的结果都为True。这是因为直接赋值都是赋值的引用,是引用,是引用,重要的事情说三遍。但如果不是通过引用赋值,而是通过切片赋值呢?

# b通过切片操作重新分配了对象,但是值和a相同
>>> b = a[:]
>>> b is a
False
>>> id(a)
48740680
>>> id(b)
48740680
>>> b == a # 但他们的值还是相等的
True

新建对象之后,b 和 a 指向了不同的内存,所以 b is a 的结果为False,而 b==a的结果为True。在这里,小编提一个问题,b[0] is a[0] 的结果呢?

答案是True。因为切片拷贝是浅拷贝,列表中的元素并未重新创建。不理解的同学请翻看之前的文章 Python中的浅拷贝与深拷贝

通常,我们关注的是值,而不是内存地址,因此 Python 代码中 == 出现的频率比 is 高。但是什么时候用 is 呢?

is 与 == 相比有一个比较大的优势,就是计算速度快,因为它不能重载,不用进行特殊的函数调用,少了函数调用的开销而直接比较两个整数 id。而 a == b 则是等同于a.__eq__(b)。继承自 object 的 __eq__ 方法比较两个对象的id,结果与 is 一样。但是多数Python的对象会覆盖object的 __eq__方法,而定义内容的相关比较,所以比较的是对象属性的值。

在变量和单例值之间比较时,应该使用 is。目前,最常使用 is 的地方是判断对象是不是 None。下面是推荐的写法:

a is None

判断不是None的推荐写法是:

a is not None

Python会对比较小的整数对象进行缓存,下次用的时候直接从缓存中获取,所以is 和 == 的结果可能相同:

>>> a = 1
>>> b = 1
>>> a is b
True
>>> a == b
True

而看一下另外一段代码:

>>> a = 257
>>> b = 257
>>> a is b
False

这是什么原因呢?

注意,Python仅仅对比较小的整数对象进行缓存(范围为范围[-5, 256])缓存起来,而并非是所有整数对象。需要注意的是,这仅仅是在命令行中执行,而在Pycharm或者保存为文件执行,结果是不一样的,这是因为解释器做了一部分优化。

总结

1、is 比较两个对象的 id 值是否相等,是否指向同一个内存地址;
2、== 比较的是两个对象的内容是否相等,值是否相等;
3、小整数对象[-5,256]在全局解释器范围内被放入缓存供重复使用;
4、is 运算符比 == 效率高,在变量和None进行比较时,应该使用 is。

(本文来源于博主kiko0o0的博客)

关于python中的is和==的区别的更多相关文章

  1. Python中type与Object的区别

    Python中type与Object的区别 在查看了Python的API后,总算明白了.现在总结如下: 先来看object的说明: Python中关于object的说明很少,甚至只有一句话: clas ...

  2. Python中生成器和迭代器的区别(代码在Python3.5下测试):

    https://blog.csdn.net/u014745194/article/details/70176117 Python中生成器和迭代器的区别(代码在Python3.5下测试):Num01–& ...

  3. Python中的is和==的区别,==判断值是否相等,is判断地址是否一致

    Python中的is和==的区别 Python中的对象包含三要素:id.type.value. 其中id用来唯一标示一个对象,type标识对象的类型,value是对象的值. is判断的是a对象是否就是 ...

  4. 基于python中staticmethod和classmethod的区别(详解)

    例子 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 class A(object):   def foo(self,x):     print "executing foo ...

  5. Python中send()和sendall()的区别

    Python中send()和sendall()的区别 估计每个学习Python网络编程的人,都会遇到过这样的问题: send()和sendall()到底有什么区别? send()和sendall()原 ...

  6. Python中的is和==的区别

    Python中的is和==的区别 1. is 是比较内存地址id() a = "YongJie" b = "YongJie" print(id(a)) #233 ...

  7. python中_new_()与_init_()的区别

    __new__方法的使用 只有继承于object的新式类才能有__new__方法,__new__方法在创建类实例对象时由Python解释器自动调用,一般不用自己定义,Python默认调用该类的直接父类 ...

  8. python中break和continue的区别

    python中break和continue的区别   break和continue 1.break 意思为结束循环   例: i = 0 while i<10:     i+=1     if ...

  9. 从python中copy与deepcopy的区别看python引用

    讨论copy与deepcopy的区别这个问题要先搞清楚python中的引用.python的内存管理. python中的一切事物皆为对象,并且规定参数的传递都是对象的引用.可能这样说听起来比较难懂,对比 ...

  10. python中input()和raw_input()的区别

    两者均是python的内置函数,通过读取控制台的输入与用户实现交互.raw_input:将所有输入作为字符串看待,不管用户输入什么类型的都会转变成字符串.                   raw的 ...

随机推荐

  1. Struts2+Hibernate4+Spring4框架整合搭建Java项目原型

    收藏 http://www.cnblogs.com/mageguoshi/p/5850956.html Struts2+Hibernate4+Spring4框架整合搭建Java项目原型

  2. MySQL数据库相关开发入门

    使用apt-get来进行MYSQL数据库的安装,安装好以后就可以使用数据库了. 命令行键入mysql即可进入(因为数据库初始化的没有密码的):当然为了安全,你最好还是创建一个用户和密码. 当你创建过用 ...

  3. <转载> FreeNAS的安装和简单配置 http://freenas.cn/?p=342

    前些日子在公司搭了一个模拟生产环境的平台.由于是测试环境,资源有限只能使用虚拟机实现,所以存储这块就想到了使用FreeNAS.很早以前玩儿过几次,当时是生产环境需要上存储设备,经过对比还是选择的更可靠 ...

  4. requestAnimFrame动画兼容性封装

    window.requestAnimFrame=function(){ return window.requestAnimationFrame ||window.webkitRequestAnimat ...

  5. Flex学习笔记-Vgropu Hgroup 定义的组 表单程序。

    <?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="ht ...

  6. hive安装教程本地模式

    1.安装模式介绍: Hive官网上介绍了Hive的3种安装方式,分别对应不同的应用场景. a.内嵌模式(元数据保村在内嵌的derby种,允许一个会话链接,尝试多个会话链接时会报错) b.本地模式(本地 ...

  7. linux 任务调度

    crontab 定时任务 -e  编辑 -l  查看 -r  删除 参数 * * * * * 分钟  小时  天数   月   星期几

  8. vue 的父组件和子组件互相获取数据和方法

    父组件主动获取子组件的数据和方法 一.ref(但不能实时更新获取) 1.调用子组件的时候 定义一个ref <child ref="headerChild"></c ...

  9. 500G JAVA视频网盘分享 (JEECG开源社区)

    500 G JAVA视频网盘分享(JEECG开源社区)   [涵盖从java入门到深入架构,Linux.云计算.分布式.大数据Hadoop.ios.Android.互联网技术应有尽有]       J ...

  10. android除去标题栏或全屏

    想要除去标题栏只要加上下面两句代码在Activity的onCreate方法中即可(要在setContentView之前添加). requestWindowFeature(Window.FEATURE_ ...