is和==的区别

来源:互联网 发布:逻辑回归算法 编辑:程序博客网 时间:2024/05/29 11:18

先看下图,
这里写图片描述
我相信计算机系的同学对这张图应该不陌生吧,如果陌生的话,你是不是挂科了!!!
学过C,C++的同学都知道指针的概念,所以上图中的“内存单元地址”就是指针,举个例子,就类似房间的门牌号,是一个指定这个房间的唯一标识。

在来说说is和==,is判断的是两个量(变量,常量)的指针是否相等,而==判断的是两个量(变量,常量)的内存单元的内容是否相等,也就是说,当两个量的指针相等的话,他们的值也必定相等;但是他们的值相等,指针不一定相等,这很好理解,也说明了为什么is要比==的执行速度快了,我程序只需要找到门牌号比较就可以了,不用找到门牌号,再通过门牌号找到门里的东西再比较,多了一步总是需要消耗时间的。下面举些例子。

# 例子1>>> a = b = "str">>> a is bTrue>>> a == bTrue# 例子2>>> a = "good_">>> b = "good_">>> a is bTrue>>> a == bTrue# 例子3>>> a = "good&">>> b = "good&">>> a is bFalse>>> a == bTrue>>> id(a)  # 查看指针编号4444934224>>> id(b)4444934226# 例子4>>> a = []>>> b = []>>> a is bFalse>>> a == bTrue>>> id(a)4444934228>>> id(b)4444934229

我们用上面的结论可以理解前两个例子,后两个怎么回事?

我们将知识点升级一下

我们说下python的intern机制:值相同的字符串对象只会保存一份,是共用的,这也决定了字符串必须是不可变对象。Python中的字符串采用了intern机制,会自动intern。

intern机制的好处是,需要值相同的字符串的时候(比如标识符),直接从池里拿来用,避免频繁的创建和销毁,提升效率,节约内存。缺点是,拼接字符串、对字符串修改之类的影响性能。因为是不可变的,所以对字符串修改不是inplace操作,要新建对象。这也是为什么拼接多字符串的时候不建议用+而用join()。join()是先计算出所有字符串的长度,然后一一拷贝,只new一次对象。
需要小心的坑,并不是所有的字符串都会采用intern机制。只包含下划线、数字、字母的字符串才会被intern

这样看的话,第3个例子就很好理解了,至于第4个例子,像list,dict,set等数据结构都是另开存储单元的。

我们将知识点再升级一下

# 例子5>>> a = "str">>> b = "st" + "r">>> a is bTrue>>> a == bTrue>>> "str" is "st" + "r"True# 例子6>>> a = "good">>> b = "goo">>> a is b + "d"False>>> a == b + "d"True

5,6两个例子比较来看,为什么例子6是False,只包含字母啊,不是应该被自动intern的么?
这里有个运算时间前后的问题,例子5中 b = “st” + “r”,是将”st” + “r” = “str”运算之后的结果存入存储单元,而结果与a变量相同,所以被intern了,故是True。例子6中在a,b比较之前,就已经定义好了两个不同的存储单元,所以他们的指针一定是不同的。

我们将知识点再再升级一下

我们经常会定义方法,而且方法里一般会有传参数,那么,你知道这个参数传的是指针还是值么?如果犹豫了,那就去验证。

>>> a = "go&">>> id(a)4445047624>>> def ss(a):...     print(id(a))... >>> ss(a)4445047624

我定义了一个a变量,它的值是不会被intern的,所以传的如果是值的话,会另开存储单元,也就是说id(门牌号)会不同,结果门牌号是相同的,故方法里传的是指针不是值。

我们将知识点再再再升级一下

>>> x = 3>>> y = 3>>> x is yTrue>>> xx = 800>>> yy = 800>>> xx is yyFalse>>> -5 is -6 + 1True>>> -6 is -7 + 1False

原因是python的内存管理,缓存了-5 - 256的对象

我们将知识点再再再再升级一下

>>> r = int('nan')  # 猜猜结果>>> a = float('nan')  # 猜猜结果>>> a == aFalse>>> a is aTrue  # 真是日了狗了,我之前下过结论:如果两个对象is是true,那么 == 也一定是true。。。世界不和谐啊>>> s = float("inf")>>> sinf>>> s == sTrue>>> s is sTrue  # 真是日了吉娃娃了,城市套路多

nan其实是NaN,是数字中的空,inf是数字中的无穷大,他们在内存中占用固定的存贮单元。。。

所谓python的坑,就是总有那么些特例,你不知道,然后。。。中招了

原创粉丝点击