Python教程: ‘==‘ 与‘is‘ 以及它们背后的小秘密

yizhihongxing

比较判断逻辑是在代码中经常使用的,在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中,每次运行是所有代码都加载到内存中,属于一个整体,并不存在这个现象。

关于字符串

'''
学习中遇到问题没人解答?小编创建了一个Python学习交流群:857662006
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
# 先来个正常的
>>> 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‘ 以及它们背后的小秘密 - Python技术站

(0)
上一篇 2023年4月2日 下午5:32
下一篇 2023年4月2日

相关文章

  • Python中切片操作的详细用法

    在利用Python解决各种实际问题的过程中,经常会遇到从某个对象中抽取部分值的情况,切片操作正是专门用于完成这一操作的有力武器。理论上而言,只要条件表达式得当,可以通过单次或多次切片操作实现任意切取目标值。切片操作的基本语法比较简单,但如果不彻底搞清楚内在逻辑,也极容易产生错误,而且这种错误有时隐蔽得比较深,难以察觉。 本文通过详细例子总结归纳了切片操作的各…

    Python开发 2023年4月2日
    00
  • Python学习:配置日志的几种方式

    作为开发者,我们可以通过以下3种方式来配置logging: 1)使用Python代码显式的创建loggers, handlers和formatters并分别调用它们的配置函数;2)创建一个日志配置文件,然后使用fileConfig()函数来读取该文件的内容;3)创建一个包含配置信息的dict,然后把它传递个dictConfig()函数; 需要说明的是,log…

    2023年4月2日
    00
  • 什么是Python装饰器?

    装饰器是Python中非常重要的一个概念,如果你会Python的基本语法,你可以写出能够跑通的代码,但是如果你想写出高效、简洁的代码,我认为离不开这些高级用法,当然也包括本文要讲解的装饰器,就如同前面提到的代码调试神器PySnooper一样,它就是主要通过装饰器调用的方式对Python代码进行调试。 1.什么是Python装饰器? 顾名思义,从字面意思就可以…

    Python开发 2023年3月31日
    00
  • Python中5大模块的使用教程(collections模块、time时间模块、random模块、os模块、sys模块)

    1. 模块的简单认识 定义: 模块就是我们把装有特定功能的代码进行归类的结果. 从代码编写的单位来看我们的程序,从小到大的顺序: 一条代码 < 语句块 < 代码块(函数,类) < 模块.我们⽬目前写的所有的py文件都是模块.引入模块的方式: import 模块 from xxx import 模块 2. collections模块 coll…

    Python开发 2023年4月2日
    00
  • Python数据类型间的相互转化及字符编码

    字符间的相互转化: 数字与字符串之间的相互转化 1、数字(整数与浮点数) –> 字符串 :只需要在要转化的数字前加str进行转换就可以 num = 10.5 str_num = str(num) print(str_num) 2、字符串转化为数字 –> 使用 int 或 float 方法进行转化 1 整数字符串转化为数字 (当字符串中只有数字…

    Python开发 2023年4月2日
    00
  • python进程池中的回调函数

    什么是回调函数 指定一个任务后、并且指定一个回调函数后,当指定的进程池执行的任务结束后,会将该任务的返回值作为回调函数的参数传递到回调函数中,并且回调函数得以执行 回调函数在主进程中被执行 import os from multiprocessing import Pool def func1(n): print(‘in func1’, os.getpid(…

    python 2023年4月17日
    00
  • Python学习: 网络请求模块 urllib 、requests

    Python 网络请求模块 urllib 、requests Python 给人的印象是抓取网页非常方便,提供这种生产力的,主要依靠的就是 urllib、requests这两个模块。 urlib 介绍 urllib.request 提供了一个 urlopen 函数,来实现获取页面。支持不同的协议、基本验证、cookie、代理等特性。 urllib 有两个版本…

    Python开发 2023年4月2日
    00
  • Python教程:类的派生

    一、派生 派生:子类中新定义的属性的这个过程叫做派生,并且需要记住子类在使用派生的属性时始终以自己的为准 1 派生方法一(类调用) 指名道姓访问某一个类的函数:该方式与继承无关 class OldboyPeople: “””由于学生和老师都是人,因此人都有姓名、年龄、性别””” school = ‘oldboy’ def __init__(self, nam…

    Python开发 2023年3月31日
    00
合作推广
合作推广
分享本页
返回顶部