在Python编程中,如果你测试两个相同的小整数变量的内存地址(使用内置的id()函数),你会惊奇地发现它们的地址是完全一样的。然而,当你对较大的整数执行相同的操作时,它们的地址却可能是不同的。这是因为Python(特指CPython实现)为了优化性能和节约内存,引入了“整数驻留”(Integer Interning)或“小整数缓存”机制。
什么是Python的整数驻留机制?
Python在启动时,会预先创建并缓存一定范围内的常用整数对象。这意味着在这个范围内的任何地方使用这些整数,Python都不会创建新的对象,而是直接引用已存在的对象。
缓存范围: 默认情况下,CPython缓存的整数范围是 -5 到 256(包含-5和256)。
这种机制的好处在于:
1. 内存效率: 避免了为频繁使用的小整数值创建数百或数千个重复的对象。
2. 速度优化: 当需要用到这些数字时,可以直接从缓存中获取,比创建新对象快得多。
代码实操:验证小整数的地址一致性
我们可以使用id()函数来获取对象的唯一标识符(即内存地址),并通过is操作符来判断两个变量是否指向同一个对象。
示例一:在缓存范围内的整数
我们选择数字 10 和 256 进行测试,它们都在 [-5, 256] 范围内。
a = 10
b = 10
print(f"a = {a}, id(a) = {id(a)}")
print(f"b = {b}, id(b) = {id(b)}")
print(f"a is b: {a is b}")
# 输出:a is b: True (地址相同)
x = 256
y = 256
print(f"\nx = {x}, id(x) = {id(x)}")
print(f"y = {y}, id(y) = {id(y)}")
print(f"x is y: {x is y}")
# 输出:x is y: True (地址相同)
如上所示,变量 a 和 b 指向同一个内存地址,x 和 y 也指向同一个内存地址。这证明了小整数被成功驻留。
示例二:超出缓存范围的整数
我们选择数字 257 进行测试,它超出了默认的缓存范围。
p = 257
q = 257
print(f"\np = {p}, id(p) = {id(p)}")
print(f"q = {q}, id(q) = {id(q)}")
print(f"p is q: {p is q}")
# 输出:p is q: False (通常情况下,地址不同)
运行结果显示,p 和 q 的内存地址通常是不同的,因为 257 超过了默认的缓存阈值,Python为每个变量创建了新的整数对象。
注意:编译时优化(Compilation Optimization)
需要注意的是,在某些情况下(例如,在一个代码块中同时定义且值完全相同的较大整数),CPython的编译器可能会在编译时进行额外的优化,使得它们最终指向同一个对象。但这种行为是编译器优化而非固定的“整数驻留”机制。当你从不同的模块或在不同的时间点创建这些对象时,它们通常会有不同的ID。
总结
Python的整数驻留机制是CPython内存管理中的一个重要组成部分。它通过预先创建和缓存范围在 [-5, 256] 之间的小整数对象,确保了这些高频使用的值在内存中只有一份副本,极大地提高了效率和内存利用率。
汤不热吧