应使用is判断单例(如None、True、False),用==判断值相等;is比较内存地址,==调用__eq__方法;小整数和短字符串的is成立是CPython缓存所致,不可依赖。

is 比较的是内存地址,不是“值”
当你写 a is b,Python 实际在比较 id(a) == id(b)——也就是两个变量是否指向**同一块内存**。它不看内容、不调用任何方法、不转换类型,纯指针比较。
常见错误现象:[1, 2] is [1, 2] 返回 False,哪怕列表一模一样;1000 is 10**3 在多数情况下也是 False,因为它们是两个独立创建的整数对象。
- 小整数(-5 到 256)和某些短字符串被 CPython 缓存,所以
100 is 100碰巧为True,但这只是实现细节,不能依赖 -
None、True、False是单例,全局唯一,is对它们是安全且语义正确的 - 自定义类无法重载
is行为,它永远只比地址
== 比较的是逻辑相等,走 __eq__ 方法
a == b 默认调用 a.__eq__(b)。内置类型(如 int、str、list)已实现合理逻辑:数值比大小、字符串比字符序列、列表比每个元素……但自定义类若没重写 __eq__,就退化成 is 行为。
常见误用:if x == None: 看似能过,但若 x 是个恶意实现 __eq__ 总返回 True 的类实例,就会误判;而 if x is None: 绝对可靠。
-
==可能触发遍历(比如比较两个大列表)、类型检查或浮点容差计算,性能不如is稳定 - numpy、pandas 等库重载了
==,返回数组而非布尔值,此时is完全不适用 - 实现
__eq__时,建议同时实现__hash__,否则实例无法放入set或作dict键
绑定方法对象:== 才是校验回调的正确方式
通过实例访问的方法(如 obj.method)每次都是新对象,obj.method is obj.method 恒为 False。这是 Python 的规范行为,不是 bug。
但 obj.method == obj.method 为 True,因为 == 被重载为比较 __self__ 和 __func__ 是否一致。
- Qt 回调、线程任务、事件处理器中需判断“是不是同一个绑定方法”,必须用
==,不能用is - 若你真要确认方法归属,可显式比较:
callback.__func__ is some_func and callback.__self__ is some_obj -
functools.partial、lambda、闭包函数等无绑定关系的对象,==不一定成立,需另寻方案
什么时候该用 is,什么时候该用 ==
原则很简单:想确认“是不是同一个东西”,用 is;想确认“值是否一样”,用 ==。95% 的数据比对场景都该用 ==。
- 必须用
is的:检查None、True、False、NotImplemented、Ellipsis这类单例 - 绝对不该用
is的:数字、字符串、列表、字典、自定义实例——哪怕它们看起来“一样” - 不确定时,优先选
==;怀疑对象复用时,才用id()或is验证
真正容易翻车的,从来不是记不住区别,而是写惯了 == 后顺手把 None 也套进去,或者看到 "hello" is "hello" 成立,就以为所有字符串都能这么比。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











