You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python不可变对象的身份特性及相关技术问询

Python中不可变对象的单例行为测试

基于Python 3.10.13(运行于Ubuntu Linux系统)执行以下测试:

整数的单例特性

已知Python中部分小整数为单例,但大整数并非如此:

>>> a = 1
>>> b = 1
>>> a is b
True
>>> a = 1000000
>>> b = 1000000
>>> a is b
False

浮点数的身份特性

所有浮点数的身份似乎互不相同:

>>> a = 0.0
>>> b = 0.0
>>> a is b
False

字符串的身份差异

原本以为每个字符串的身份也各不相同,但实际测试发现:

>>> a = "1024"
>>> b = "1024"
>>> a is b
True

然而:

>>> a = str(2**10)
>>> b = str(2**10)
>>> a is b
False

元组的身份特性

元组与浮点数类似,身份互不相同:

>>> a = (1,2,3)
>>> b = (1,2,3)
>>> a is b
False

问题解答

1. 上述行为是Python的刻意设计,还是实现过程中无关紧要的附带结果?

这些行为大多是CPython实现层面的优化附带结果,并非Python语言规范强制要求的设计。Python标准仅明确is用于比较对象身份、==用于比较值相等,但没规定不可变对象必须复用实例。不过小整数的单例是CPython的刻意优化——小整数在代码中出现频率极高,预存复用能减少内存占用、提升运行效率。

2. 若为实现附带结果,为何字符串与元组、浮点数的表现不同,且字符串的身份还取决于创建方式?

  • 字符串的差异:CPython有「字符串驻留(string interning)」优化,会自动复用符合规则的字符串实例。比如直接用字面量定义的字符串(如"1024"),如果只包含字母、数字、下划线,会被加入驻留池复用;但通过str()这类函数动态生成的字符串,除非显式调用sys.intern(),否则不会自动驻留,因此会生成新实例。
  • 浮点数与元组:浮点数的数值空间极大,无法像小整数那样预存所有常用值;而元组即使内容相同,创建时也默认生成新实例——因为元组可以包含可变对象,预存复用的收益极低,还可能引发意外问题,所以CPython没做这类优化。

3. 除使用==比较不可变对象外,还有哪些场景需要注意该行为?

  • 判断内置单例对象:None、True、False是Python内置的单例,用is判断是安全且推荐的,比如if x is None:。
  • 函数默认参数:如果依赖不可变对象的身份判断默认参数,可能踩坑——比如有人错误用is判断默认传入的字符串是否为初始值,结果因为驻留机制导致判断逻辑出错。
  • 自定义缓存逻辑:自己实现对象缓存时,要注意CPython的自动驻留/单例机制可能干扰预期,比如误以为生成了新实例,实际却复用了旧的。
  • 内存调试分析:排查内存泄漏时,要注意单例/驻留对象的存在,避免误判对象的实际创建次数。

内容的提问来源于stack exchange,提问作者doetoe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.01 16:34:52