Python中整数缓存的3个事实

引言

Python 有一个称为整数缓存的特殊功能。有时候,它可能会让我们感到困惑。例如,如果我们在 Python shell 上运行下面的代码,结果是令人惊讶的:

>>> a=256
>>> b=256
>>> a is b
True
>>> x=257
>>> y=257
>>> x is y
False

为什么256是256,而257不是257?有什么问题吗?

这还不是最奇怪的部分,如果我们把相同的代码放到一个文件中,并以 Python 脚本的形式运行它,结果会再次让我们大吃一惊!

a = 256
b = 256
print(a is b)
x = 257
y = 257
print(x is y)

我们将所有代码放入上面的脚本“ test.py”中,然后打开一个终端并运行脚本:

$ python test.py
True
True

如果你对这些也感到困惑,那就不用担心了。本文将揭示整数缓存特性的工作原理,并将其总结为三个事实。读完之后,你就不会再对它感到困惑了。

1. Python中的一小部分整数是Singleton

实际上,为了节省时间和内存开销,Python 总是预加载[-5,256]范围内的所有小整数。当在这个范围内声明一个新的整数变量时,Python 只是将缓存的整数引用到它,不会创建任何新的对象。

换句话说,[-5,256]中的所有整数都是Singletons,它们已经被保存在内存中了。我们不能在这个范围内创建新的整数对象。

因此,对第一个例子的解释是显而易见的:

· 当变量a及b 被分配到256上,它们被引用到存放256的同一个存储位置,他们指向同一个对象。

· 当变量a及b被分配给257,他们是两个不同的对象在不同的内存位置。

由于 is 操作符用于比较两个变量的内存位置,因此 a is b 应该输出 True,x is y 应该输出 False。

我们还可以使用 id ()函数,它打印出变量的内存位置,以证实上述解释:

>>> a=256
>>> b=256
>>> id(a)==id(b)
True
>>> x=257
>>> y=257
>>> id(x)==id(y)
False

2.如果python编译器可以看到全部,则情况就不一样了

如前所示,如果我们运行与 Python 脚本相同的代码,x = y 将输出 True。这当然不是偶然的。

事实上,Python 编译器是非常聪明的,并且会在引擎盖下为我们做许多优化。如果我们将代码作为一个整体运行,Python 编译器可以立即“看到”整个程序并进行相应的优化。

至于我们的例子,因为 Python 编译器看到了整个程序,它知道有两个变量 x 和 y,它们等于同一个整数257。因此,创建一个整数对象并将两个变量引用到其中是合理的。这种优化可以节省时间和内存成本。

但是,如果我们在交互式 Python shell 中逐行运行代码,编译器每次只能看到一行代码。

这意味着当我们输入 y = 257时,编译器只能看到这一行代码,而不能记住之前的代码 x = 257。因为257不在特殊范围内(即[-5,256]) ,所以会创建一个新的整数对象。

因为我们知道 Python 编译器的这个特性,所以我们可以使用一个技巧在交互式 shell 中使 x is y 输出为 True:

>>> x=257; y=257
>>> x is y
True

3. Python的实现和版本会影响整数缓存功能

上述所有示例和解释都基于 CPython,它是 Python 的标准实现。事实上,有一些替代的实现,比如 PyPy、 IronPython 和 Jython,它们的一些机制可能与 CPython 不同。

例如,在 PyPy 中,默认情况下禁用小整数缓存特性。如果我们想打开这个特性,我们应该首先启用它。有关详细信息,我们可以查看相应的 PyPy 文档。

此外,Python 的版本也很重要。我们在本文中使用的是 Python 3.8。由于 Python 是不断更新和发展的,没有人能够确保在未来的版本中不会改变一个特殊的功能。

总结

Python 内部有许多优化机制,我们应该了解它是如何工作的并影响我们的代码。整数缓存特性对于减少时间和内存开销是非常有用和必要的。

·  END  ·

HAPPY LIFE

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值