Python预赋值与用户输入变量中字符串、整数标签(id)分配差异原因
预赋值与用户输入场景下整数、字符串id分配差异原因
这种差异本质是CPython解释器内置的对象缓存复用机制导致的,我们分别结合两类测试用例说明:
1. 整数场景逻辑
CPython实现了小整数池优化:解释器启动时会预先创建好[-5, 256]区间内的所有整数对象,所有引用到这个区间值的变量,都会直接指向同一个缓存对象,不会重复创建。
如果整数超出[-5, 256]范围,Python不会做全局缓存,仅同一代码块内字面量赋值的相同大整数会被临时复用,动态生成(运算、类型转换得到)的大整数都会作为新对象创建。
对应测试1的结果说明
测试代码:
# 整数场景测试 a=3 b = input() # input默认返回字符串类型 c=3 d = int(input()) # 输入被强制转换为整数类型 # 假设b和d的输入值均为3 print(id(a)) print(id(b)) print(id(c)) print(id(d)) print(a is b) print(c is d)
运行结果逻辑:
- a和c都是字面量赋值的整数3,属于小整数池范围,二者id完全相同
- b是input返回的字符串'3',和整数3类型不同,id和a完全不同,
a is b固定返回False - d是
int(input())转换得到的整数3,属于小整数池范围,会复用缓存对象,所以id和a、c相同,c is d返回True
注意:如果输入值为超出小整数池的整数(比如257),那么d是动态转换得到的新对象,id会和预赋值的257不同,
c is d会返回False
2. 字符串场景逻辑
CPython实现了字符串驻留(Intern) 优化:符合规则的字符串会被全局缓存,相同值的字符串会指向同一个内存对象,id一致。默认触发驻留的条件为:
- 仅包含字母、数字、下划线的字符串字面量
- 长度较短(不同CPython版本阈值不同,通常为20以内)
动态生成的字符串(包括input输入得到、字符串拼接、切片得到的字符串)默认不会触发全局驻留,哪怕值和已缓存的驻留字符串完全一致,也会作为新对象创建。
对应测试2的结果说明
测试代码:
# 字符串场景测试 s1 = "abc" s2 = input('Enter a String : ') # 假设s2输入值为abc print(s1 == s2) print(s1 is s2) s3 = "abc" print(s1 is s3) print(s2 is s3) print(id(s1)) print(id(s2)) print(id(s3))
运行结果逻辑:
- s1和s3都是字面量赋值的"abc",符合驻留条件,二者id完全相同,
s1 is s3返回True - s2是input动态输入得到的字符串,不会触发驻留,是新创建的对象,所以id和s1、s3都不同,
s1 is s2、s2 is s3都返回False ==运算符比较的是字符串的值而非内存地址,所以s1 == s2返回True
补充注意
永远不要用is运算符判断两个变量的值是否相等,is仅用于判断两个变量是否指向同一个内存对象,值相等判断请统一使用==运算符。
内容的提问来源于stack exchange,提问作者INDRA BHUSHAN THAKUR
相关产品推荐
相关产品推荐

