摘要

  比较判断逻辑是在代码中经常使用的,在Python中常用 '==' 和 is 来做比较判断。

  • ==  :  双等号是用来比较变量所指向内存单元中的值是否相等,它只关心值,并不在意值的内存地址,也就是说可以是两个不同内存地址的值相等。
  • is    :  它用来比较两个变量是不是指向同一个内存单元,虽然它也可以比较值,但是它更加关心的是内存地址是否一样,当然内存地址一样值也就是一样的。

关于整数

# 按照逻辑,下面的代码很正常
>>> a = 1
>>> b = 1
>>> a == b
True
>>> a is b
True
>>> id(a)
1570522768
>>> id(b)
1570522768
# 下面就是颠覆认知的时刻
>>> a = 1000
>>> b = 1000
>>> a == b
True
>>> a is b
False
>>> id(a)
81183344
>>> id(b)
81183376

  是的,两个相同值的变量,内存地址不一样了。当然产生这个现象的前提条件是用python命令行去执行,而不是用pycharm之类的编辑器。其根本原因也就是python解释器的问题,涉及到python的垃圾回收机制。上面现象的原因是因为一个叫做小整数对象池的东西。

   Python为了优化速度,会把 [-5, 256] 之间的数据提前存放在小整数池中,如果程序使用到小整数池中的数据,是不会开辟新的内存空间去创建,而是指向对象池中的同一份数据,也就是说有N个变量等于1的话,那么这N个变量的内存地址都会指向小整数池中的1位置。小整数池的使用是为了避免整数频繁申请和销毁内存空间。小整数池是提前建立好的,不会被垃圾回收。

  当数据超出小整数池后,也就是范围到了大整数对象池中了,系统每次都会申请一块新内存来存储数据,这个'is'不等于'=='的现象也就不存在了。

  pycharm中,每次运行是所有代码都加载到内存中,属于一个整体,并不存在这个现象。

关于字符串 

# 先来个正常的
>>> a = 'qwe'
>>> b = 'qwe'
>>> a == b
True
>>> a is b
True
>>> id(a)
81797024
>>> id(b)
81797024
# 感觉没什么变化,那就加长一些
>>> a = 'q' * 20
>>> b = 'q' * 20
>>> a is b
True
>>> a == b
True
# 在长点就不一样了
>>> b = 'q' * 21
>>> a = 'q' * 21
>>> a is b
False
>>> a == b
True
>>> id(a)
81811696
>>> id(b)
81811600

  产生原因:Python的intern机制

  简单理解有点像缓存的意思,当需要使用相同的字符串时(变量赋值),直接从缓存中拿出来用而不是重新创建,这样可以避免频繁的创建和销毁,提升效率,节约内存。缺点是拼接字符串,对字符串修改之类的影响性能。因为是不可变的,所以对字符串修改不是inplace操作,而是新建对象。这也就是拼接字符串的时候不建议是用 '+' 方法,而是推荐用join 函数,join函数是先计算出所有字符串的长度,然后一一拷贝,而只创建一次对象。每个'+'方法都是创建一次新对象。当字符串长度超过20时,也不会使用intern机制。

  并不是所有的字符串都会采用intern机制。只包含下划线字母(包含大小写)数字的字符串才会被intern。空格和一些特殊字符都不在内。也就是说字符串中如果包含空格和其他一些特殊符号(除去下划线),python都不会应用intern机制,而是直接开辟新的内存空间去存储。

# 注意下面这种看似合理的字符串intern
>>> 'ab' + 'c' is 'abc' # 这里的字符串,'ab' + 'c' 是在complie time 求值的,被替换成了'abc'
True
>>> n1 = 'ab'
>>> n2 = 'abc'
>>> n1 + 'c' is n2 # n1 + 'c' 是在run-time拼接,导致没有被自动intern
False
>>> n1 + 'c' is 'abc'
False
>>> n1 + 'c' == 'abc'
True
>>> n1 + 'c' == n2
True

Python中 '==' 与'is' 以及它们背后的故事的更多相关文章

  1. PySpark 的背后原理--在Driver端,通过Py4j实现在Python中调用Java的方法.pyspark.executor 端一个Executor上同时运行多少个Task,就会有多少个对应的pyspark.worker进程。

    PySpark 的背后原理 Spark主要是由Scala语言开发,为了方便和其他系统集成而不引入scala相关依赖,部分实现使用Java语言开发,例如External Shuffle Service等 ...

  2. 深刻理解Python中的元类metaclass(转)

    本文由 伯乐在线 - bigship 翻译 英文出处:stackoverflow 译文:http://blog.jobbole.com/21351/ 译注:这是一篇在Stack overflow上很热 ...

  3. 深刻理解Python中的元类(metaclass)

    译注:这是一篇在Stack overflow上很热的帖子.提问者自称已经掌握了有关Python OOP编程中的各种概念,但始终觉得元类(metaclass)难以理解.他知道这肯定和自省有关,但仍然觉得 ...

  4. python中的builtin函数详解-第二篇

    classmethod(function) 这里不过多说明这个builtin方法的具体用法,python的文档和help函数已经给了这个方法充足的使用说明,所以我这里要说的时关于 classmetho ...

  5. 可爱的 Python : Python中的函数式编程,第三部分

    英文原文:Charming Python: Functional programming in Python, Part 3,翻译:开源中国 摘要:  作者David Mertz在其文章<可爱的 ...

  6. [转] 深刻理解Python中的元类(metaclass)

    非常详细的一篇深入讲解Python中metaclass的文章,感谢伯乐在线-bigship翻译及作者,转载收藏. 本文由 伯乐在线 - bigship 翻译.未经许可,禁止转载!英文出处:stacko ...

  7. Python中导入第三方声源库Acoular的逻辑解释以及Acoular的下载

    [声明]欢迎转载,但请保留文章原始出处→_→ 秦学苦练:http://www.cnblogs.com/Qinstudy/ 文章来源:http://www.cnblogs.com/Qinstudy/p/ ...

  8. 盘点 Python 中的那些冷知识(一)

    小明在日常Code中遇到一些好玩,冷门的事情,通常都会记录下来. 现在已经积攒了一些了,最近打算整理一波,发出来给大家补补.一篇只分享五个,有时间了就整理.不想错过的,千万记得关注一下. 1. 省略号 ...

  9. python中的__metaclass__

    什么是元类: python中类也是一种对象, 可以称为类对象. 元类就是用来创建类对象的"东西". 你创建类就是为了创建类的实例对象, 不是吗? 但是我们已经学习了python中的 ...

随机推荐

  1. Spring Boot 、mybatis 、swagger 和 c3p0 整合

    文件路径如下 添加依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns=" ...

  2. oracle忘记密码,修改密码

    1:输入命令: sqlplus /nolog ,进入oracle控制台,并输入 conn /as sysdba;以DBA角色进入.2:若修改某一个用户密码, 修改用户口令 格式为:alter user ...

  3. fiddler手机抓包

    配置好之后,发现手机不能连接代理服务器,用netstat发现根本就没有手机的ip地址,于是猜想是不是防火墙的问题,关闭防火墙果然能连上,开启防火墙又连不上了,这就说明确实是防火墙的问题,关闭防火墙又很 ...

  4. button作用类似于submit

    不想提交,可使用以下 <a href="javascript:;" >修改</a>

  5. 我读《从Paxos到zookeeper分布式一致性原理与实践》

    从年后拿到这本书开始阅读,到准备系统分析师考试之前,终于读完了一遍,对Zookeeper有了一个全面的认识,整本书从理论到应用再到细节的阐述,内容安排从逻辑性和实用性上都是很优秀的,对全面认识Zook ...

  6. 10 Consensus and Profile

    Problem A matrix is a rectangular table of values divided into rows and columns. An m×nm×n matrix ha ...

  7. centos下修改文件后如何保存退出

    centos下修改文件后如何保存退出 保存命令 按ESC键 跳到命令模式,然后: :w 保存文件但不退出vi :w file 将修改另外保存到file中,不退出vi :w! 强制保存,不推出vi :w ...

  8. VS2010+SVN

    小乌龟版本用1.6,用1.8时老报错SVN是2.06, SVN Server是2.1.9

  9. CodeForces 687A NP-Hard Problem (二分图)

    题意:给定 n 条边,然后让你把它分成两组,每组都有所有边的一个端点. 析:一开始我是先判定环,以为就不能成立,其实不是这样的,有环也行.用dfs进行搜索,并标记每一个端点,如果标记过并且和以前不一样 ...

  10. loadrunner - Run time Settings 的详细说明

    本文主要讲解一下run-time settings(如图1所示)里各设置项的具体含义(注:标红色的选项卡是比较值得关注的,可重点看一下): 图1 1.General / Run Logic 选项卡   ...