gpt4 book ai didi

python - 为什么 Python 处理 '1 is 1**2' 与 '1000 is 10**3' 不同?

转载 作者:IT老高 更新时间:2023-10-28 22:21:31 25 4
gpt4 key购买 nike

灵感来自 this关于缓存小整数和字符串的问题我发现了以下我不理解的行为。

>>> 1000 is 10**3
False

我以为我理解了这种行为:1000 太大了要缓存。 1000 和 10**3 指向 2 个不同的对象。但我错了:

>>> 1000 is 1000
True

所以,也许 Python 对计算的处理与“普通”整数不同。但这个假设也不正确:

>>> 1 is 1**2
True

如何解释这种行为?

最佳答案

这里发生了两件不同的事情:Python 将 int 文字(和其他文字)存储为带有已编译字节码的常量 小整数对象被缓存为单例。

当你运行 1000 is 1000 时,只有一个这样的常量被存储和重用。你真的在看同一个物体:

>>> import dis
>>> compile('1000 is 1000', '<stdin>', 'eval').co_consts
(1000,)
>>> dis.dis(compile('1000 is 1000', '<stdin>', 'eval'))
1 0 LOAD_CONST 0 (1000)
3 LOAD_CONST 0 (1000)
6 COMPARE_OP 8 (is)
9 RETURN_VALUE

这里的LOAD_CONST指的是索引0处的常量;您可以在字节码对象的 .co_consts 属性中看到存储的常量。

将此与 1000 is 10 ** 3 的情况进行比较:

>>> compile('1000 is 10**3', '<stdin>', 'eval').co_consts
(1000, 10, 3, 1000)
>>> dis.dis(compile('1000 is 10**3', '<stdin>', 'eval'))
1 0 LOAD_CONST 0 (1000)
3 LOAD_CONST 3 (1000)
6 COMPARE_OP 8 (is)
9 RETURN_VALUE

有一个窥孔优化,在编译时预先计算常量上的表达式,这个优化已经用 1000 替换了 10 ** 3,但是优化没有t 重用预先存在的常量。因此,LOAD_CONST 操作码在索引 0 和 3 处加载两个不同的整数对象,它们是两个 不同的 int 对象。

然后在 small integers are interned 的地方进行了优化。 ;在 Python 程序的生命周期中,只创建了一个 1 对象的副本;这适用于 -5 到 256 之间的所有整数。

因此,对于 1 是 1**2 的情况,Python 内部使用来自内部缓存的单例 int() 对象。这是一个 CPython 实现细节。

这个故事的寓意是,当您真正想按值进行比较时,永远不要使用 is。始终将 == 用于整数。

关于python - 为什么 Python 处理 '1 is 1**2' 与 '1000 is 10**3' 不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21880308/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com