整数缓存与 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% 的作用域谜题都能解开。
挑战任务
正确的比较
判断变量是否为 None,以及两个列表值是否相等。
课后作业
安全的值比较
写个函数 safe_compare(a, b),正确比较两个值是否相等,别用 is。