is 比较内存地址,== 比较值;仅对 none、true、false 等单例对象用 is,其余一律用 ==,否则易因对象复用或自定义 eq 导致误判。

is 和 == 看似都做“比较”,但底层逻辑完全不同:前者比内存地址,后者比对象的值。误用 is 判断值相等,是 Python 新手最常踩的隐性坑之一。
什么时候必须用 is?只有一种情况:判断是否为 None 或其他单例
Python 中 None、True、False 是单例对象,全局唯一。所以 a is None 是标准写法;而 a == None 虽然多数时候不报错,但若 a 实现了自定义 __eq__(比如某个类重载了 == 返回 True),就可能意外通过判断。
-
if x is None:✅ 安全、明确、符合 PEP 8 -
if x == None:❌ 不推荐,语义模糊,有潜在风险 -
if not x:⚠️ 更危险——它还会把0、[]、""当作假值过滤掉,和“是否为None”不是一回事
is 对可变对象(如列表、字典)几乎总返回 False,哪怕内容一模一样
因为每次写 [1,2,3] 都会新建一个对象,分配新内存地址。即使两个列表元素完全相同,它们的 id() 也不同。
a = [1, 2, 3] b = [1, 2, 3] print(a == b) # True print(a is b) # False print(id(a) == id(b)) # False
- 用
is比较两个字面量构造的列表/字典/集合,结果几乎总是False - 只有当变量真正共享引用时,
is才为True:b = a后,a is b才成立 - 想确认“是否同一份数据被多处修改”,才需要
is;想确认“内容是否一致”,必须用==
小整数和短字符串会“缓存”,导致 is 偶尔碰巧为 True,但这不可靠
CPython 对小整数(通常 -5 到 256)和部分短字符串做了对象复用优化。所以:
x = 100 y = 100 print(x is y) # True(但这是实现细节,不是语言保证) <p>s1 = "hello" s2 = "hello" print(s1 is s2) # 很可能 True(interned 字符串)</p><p>s3 = "hello world" s4 = "hello world" print(s3 is s4) # 极大概率 False(不保证 intern) </p>
- 这种行为依赖具体 Python 实现(如 CPython)和版本,PyPy 或其他解释器可能不同
- 绝不能把
is当作==的快捷写法来用,尤其在跨环境部署或单元测试中 - 如果真要验证是否“值相等”,无条件用
==;is只保留给None、True、False这类明确的单例检查
最易被忽略的一点:is 的行为和对象的生命周期强相关。比如函数内临时创建的空列表,在函数退出后被销毁,下次调用又建一个新对象——你以为两次 is 比较的是“同一个空列表”,其实根本不是。别依赖表象,盯住语义:你到底想问“是不是同一个东西”,还是“长得一不一样”。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











