15 分钟
Python 进阶

整数缓存与 is/== 陷阱

为什么 -5 到 256 是同一个对象,257 却不保证

  • 理解小整数缓存池机制
  • 区分 is 和 == 的本质区别
  • 知道何时用 is 何时用 ==

整数缓存与 is/== 陷阱

这是 Python 里一个看起来像玄学、实则有深刻原理的特性。

奇怪的现象

示例代码(可运行)
ℹ️小整数缓存池

CPython 启动时预创建了 -5 到 256 的所有整数对象,共 262 个,作为单例全局共享。这些小整数用得特别多,缓存能省掉重复创建销毁的开销,提性能还省内存。这个范围是硬编码的,别依赖它。

is vs ==

示例代码(可运行)
⚠️字符串驻留

和小整数类似,Python 也会驻留(intern)某些字符串,比如符合标识符规则的字符串、短字符串,这会导致 s is t 可能为 True。但这是实现细节,不同环境的行为不一样。永远用 == 比较字符串!

实际影响

示例代码(可运行)
🐍资深工程师经验谈

is 比较的是 id()(内存地址),== 调用 __eq__ 方法。绝大多数情况下用 ==。唯一例外是判断 None:用 is None,因为 None 是单例,is 更快且不会被 __eq__ 重载欺骗。这个知识点面试常考。

选择题

比较两个列表内容是否相同应该用 ==。

预测输出
x = None
print(x is None)
print(x == None)

资深工程师加餐

底层原理 · 大厂视角 · 工程经验,点卡片展开

内层函数(或 lambda)捕获的是外层变量本身,而不是定义那一刻的值;循环里定义的多个函数,循环结束后调用往往都拿到最后的值。解决办法是用默认参数 f(x=x) 立即绑定,或用工厂函数包一层。配合 LEGB 作用域顺序(局部→外层→全局→内建)理解,90% 的作用域谜题都能解开。

挑战任务

正确的比较

简单+50 XP

判断变量是否为 None,以及两个列表值是否相等。

正确的比较
2 个测试用例

课后作业

安全的值比较

中等+15 XP

写个函数 safe_compare(a, b),正确比较两个值是否相等,别用 is。

安全的值比较
1 个测试用例