None 和布尔单例必须用 is 判断,因 == 可能触发自定义 eq 导致错误;is 比较内存地址,== 比较值;小整数和短字符串驻留是实现细节,不可依赖;判断空列表应使用 == [] 或 not data,而非 is []。

判断 None 必须用 is,其他多数情况该用 ==
当你写 if x is None:,是在确认 x 是否指向那个唯一的 None 对象——这安全、高效、语义清晰。但换成 if x == None:,就可能触发自定义类的 __eq__ 方法,比如 pandas.Series 会抛出 AmbiguousValueError。同理,if flag is True 或 is False 是明确判断布尔单例,而 == True 在某些重载了 __eq__ 的对象上会返回数组或标量,导致运行时错误。
is 比较的是 id(),不是值;== 调用的是 __eq__
is 的行为等价于 id(a) == id(b),它不看内容,只认内存地址。这意味着:
-
[1, 2] is [1, 2]→False(两个独立列表,哪怕内容一模一样) -
a = []; b = a; a is b→True(b是a的别名) -
1000 is (999 + 1)→ 在 CPython 交互式环境里可能为True,但在函数中常为False,不可预测 -
"hello world" is "hello world"→ 大概率False(空格导致未驻留)
小整数和字符串驻留是实现细节,不是语言保证
CPython 缓存了 -5 到 256 的整数和部分短字符串,所以 100 is 100 或 "abc" is "abc" 看似“管用”,但这只是解释器优化:
-
257 is 257在模块顶层可能是True,但在函数内执行就是False -
sys.getsizeof("a" * 1000) != sys.getsizeof("a" * 1000)可能成立——因为长字符串不驻留 - PyPy、Jython 或未来 CPython 版本可能改变缓存策略,代码会悄无声息地出错
自定义类让 is 和 == 的差异更明显
如果你定义了一个 User 类,并按业务逻辑把 user_id 相同视为“相等”,那必须重写 __eq__:
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
class User:
def __init__(self, user_id):
self.user_id = user_id
def __eq__(self, other):
return isinstance(other, User) and self.user_id == other.user_id
这时 u1 == u2 可以返回 True,但 u1 is u2 仍只在它们真是同一个实例时才为 True。强行用 is 替代 ==,等于把“语义相等”降级为“物理同一”,业务逻辑就断了。
真正容易被忽略的是:你写 if data is []:,其实是在问“data 是不是我手敲出来的那个空列表对象”,而不是“data 是不是空的”。这种问题在动态数据(用户输入、API 响应、配置解析)里几乎从不成立。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










