ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Python 里 `is` 和 `==` 到底差在哪?5 个让你怀疑人生的案例 + 对照表

Python 里 `is` 和 `==` 到底差在哪?5 个让你怀疑人生的案例 + 对照表 Python 里is和到底差在哪5 个让你怀疑人生的案例 对照表先给结论is比的是两个变量是不是同一个对象内存地址相同相当于id(a) id(b)比的是两个对象的值相不相等调用a.__eq__(b)。一个是身份证号层面的比较一个是长得像不像的比较。这俩从根上就不是一回事混用是 Python 新手最常踩、也最隐蔽的坑。下面用 5 个真实场景把这层窗户纸捅破每个都附代码和可照搬的结论。一、小整数池为什么256 is 256是 True但257 is 257是 FalsePython 为了省内存把-5到256之间的整数在解释器启动时预先创建好并缓存全局共用同一批对象。所以a256b256print(aisb)# True命中小整数池是同一个对象c257d257print(cisd)# False超出缓存范围各建各的注意这个结论只在交互式环境逐行执行时稳定。如果在同一个.py文件的函数外连续写c 257; d 257部分 Python 实现会因为常量折叠把 257 合并成一个对象is反而可能返回 True。这正是坑点——结果依赖运行环境你没法保证。正确写法比较数值永远用别用is。二、字符串驻留为什么有的字符串is相等有的不相等字符串也有类似的驻留intern机制但规则比整数更迷惑s1hellos2helloprint(s1iss2)# True编译期常量被合并s3hello worlds4hello worldprint(s3iss4)# 通常 True短字符串常量ahellobhello# 编译期拼接等价于 helloprint(aisb)# Truexhelloyhelzylo# 运行时拼接不是常量print(xisz)# False运行时生成的新对象关键差异只有编译期就能确定的字符串常量才可能被驻留凡是涉及运行时变量拼接的几乎一定产生新对象。所以is比较字符串永远不可靠。正确写法字符串相等用。三、单例判等只有None/True/False才该用is有一类对象 Python 保证全局只有一个实例这时候用is是规范且推荐的xNoneprint(xisNone)# ✅ 正确写法print(xNone)# ⚠️ 能跑但不符合 PEP 8且可能被 __eq__ 重载坑flagTrueprint(flagisTrue)# ✅ 判断布尔身份用 is为什么 None危险因为某些对象可以重载__eq__让obj None返回True但obj is None一定是False。判断是不是没有值用is None才是铁律。PEP 8 明确建议None的比较用is/is not。四、容器内容相同is永远是 False哪怕两个列表长得一模一样只要不是同一个对象is就返回 Falselist_a[1,2,3]list_b[1,2,3]print(list_alist_b)# True值相等print(list_aislist_b)# False两个独立对象dict_a{k:1}dict_b{k:1}print(dict_aisdict_b)# False这里会递归比较每个元素列表元素再比字典比键值对。而is只看是不是内存里同一个盒子。绝大多数业务场景你要的都是内容一样所以用。五、自定义类重写__eq__后和is会彻底分家classPoint:def__init__(self,x,y):self.xx self.yydef__eq__(self,other):returnisinstance(other,Point)andself.xother.xandself.yother.y p1Point(1,2)p2Point(1,2)print(p1p2)# True__eq__ 说值相等print(p1isp2)# False是两个不同实例重写__eq__只影响完全不影响is。更进一步如果__eq__里写了会抛异常的逻辑比如比较类型不符时 raise会炸而is永远不会炸——因为is根本不调用任何方法纯粹比内存地址。这也是为什么当你想判断这两个引用指向的不是同一个东西时用a is not b最稳。六、一张表看清区别维度is比较内容对象身份id相同对象值__eq__结果是否调用方法不调用纯内存地址比较调用__eq__可能抛异常适用场景None/True/False单例判等数值、字符串、容器等内容比较小整数/驻留影响受缓存机制干扰结果不稳定不受影响稳定性能极快一次指针比较略慢可能递归遍历常见误用用is比256以外的整数/字符串几乎无除非__eq__有坑七、什么时候该用哪个记住这三条就够了判断是不是None、是不是某个单例用is/is not这是 Python 社区的硬性规范。判断数值、字符串、列表内容是否相等一律用别碰is。需要确认两个变量是不是严格指向同一个对象比如防止重复传同一个可变对象用a is b。最后再强调一遍is快但它比较的是身份不是值一旦你关心的是值就老老实实写。靠小整数池和字符串驻留的巧合写出a is b返回 True是埋了一颗随时换环境就炸的雷。你之前有没有被257 is 257在脚本里返回 True、到交互环境却返回 False 这种事坑过评论区说说你踩过的is/陷阱。
返回列表