is 不能替代 ==,因为 is 比较对象内存地址(是否同一对象),== 比较值是否相等(由 eq 控制);判断 None 必须用 is,其余多数情况应使用 ==。

is 不能替代 ==,因为它们解决的是两类根本不同的问题:一个是“是不是同一个东西”,另一个是“长得一不一样”。拿错钥匙开不了门,不是钥匙不好,而是用错了锁。
is 比较的是对象的内存地址,不是内容
Python 中每个对象在内存里都有唯一地址,id() 能看到。只要两个变量指向同一块内存,is 就返回 True;哪怕内容一模一样但分开放,is 就是 False。
-
[] is []→False(两个空列表各自独立分配内存) -
a = []; b = a; a is b→True(b是a的别名,共享地址) -
1000 is 10**3→ 在 CPython 中可能为False(小整数-5到256会缓存,但大整数不保证)
== 比较的是对象的值,由 __eq__ 方法控制
== 的行为取决于类怎么实现 __eq__。内置类型如 list、dict、str 都重载了它,做的是深度值比较。
-
[1, 2] == [1, 2]→True(元素相同,顺序一致) -
{'a': 1} == {'a': 1}→True(键值对完全一致) - 自定义类若没写
__eq__,默认退化为is,这时候误用is看似“碰巧”对,实则脆弱
判断 None 必须用 is,其他多数情况该用 ==
None 是单例,全程序只有一个实例,所以 val is None 安全、高效、语义明确。但拿 is 去判字符串、数字、列表是否“相等”,基本等于靠运气。
立即学习“Python免费学习笔记(深入)”;
- ✅ 正确:
if result is None:、if x is not None: - ❌ 危险:
if name is "admin"(字符串字面量可能被驻留,但不可靠) - ❌ 错误:
if data is [](永远为False,除非data真的就是那个空列表对象本身) - ⚠️ 隐患:
if user_input is "yes"—— 用户输入是新创建的字符串对象,is必败
容易踩的坑:小整数缓存和字符串驻留误导直觉
CPython 对小整数(-5 到 256)和某些字符串字面量做了对象复用,导致 is 偶尔“碰对”,但这属于实现细节,不是语言规范,跨解释器或版本可能失效。
-
100 is (99 + 1)→ 在 CPython 中常为True,但不应依赖 -
"hello" is "hello"→ 字符串驻留让它为True,但"hello world" is "hello world"不一定 -
is的结果无法预测,而==的行为稳定可预期
最常被忽略的一点:当你写 if x is y:,你其实在问“x 和 y 是不是同一个对象”,而不是“它们有没有相同的意义”。多数业务逻辑关心的是后者,不是前者。强行用 is 替代 ==,就像用螺丝刀撬罐头——不是做不到,而是拧歪了还划手。


















