Python中的小整数缓存会产生不明确的结果

ojsjcaue  于 2023-04-19  发布在  Python
关注(0)|答案(1)|浏览(107)

我现在正在学习Python,我偶然发现了一个奇怪的东西,我真的无法解释:
正如Python documentation中所说:
当前的实现为-5到256之间的所有整数保留了一个整数对象数组。当你在这个范围内创建一个int时,你实际上只是得到了一个对现有对象的引用。
如果我看一下intobject.c的实现,我会看到定义为NSMALLNEGINTSNSMALLPOSINTS的相同值范围。
所以当我测试一些明显的东西比如

a = 1
b = 1
print(id(a) == id(b)) # True

我在任何地方都得到相同的结果。
然而,当我移动到更大的数字时(当我说“更大”时,我的意思是超过256),我开始得到不同的结果,这些结果因IDE而异。例如:

a=2**100
b=2**100

print(id(a) == id(b))

a = 1267650600228229401496703205376
b = 1267650600228229401496703205376

print(id(a) == id(b))

在VsCode www.example.com文件中给出了FalseTruetest.py,如果我使用Visual Studio 2022,它也会在Jupiter Notebook文件中给出FalseFalse
或者类似于:

a=259
b=259

print(id(a) == id(b))

在Visual Studio和一个随机的在线Python编译器中给出True,但在Jupiter Notebook文件中给出false。
谁能解释一下整数缓存是如何工作的?我想它不完全受Python运行时的影响吧?
更新:所以我读了IainShelvington的一条评论,它看起来像是一个关于oneliner的编译器行为。但不完全是这样。看看下面的片段,你会注意到,对于中间有操作数的大数字(例如2**100)id比较返回False,而不管在何处运行代码,至于JupiterNotebook,它确实看起来像,因为它逐行执行-如果它们在不同的行上,它不会优化整数:

# The following code returns 
# (In VisualStudio 2022, VsCode (ver 1.77.3) and a few random online compilers):

#True
#True
#True
#False
#True
#===========
#True
#True
#True
#False
#True

# However in JupiterNotebook it returns:

#True
#True
#True
#False
#True
#===========
#True
#False
#False
#False
#False

a, b = 200, 200
print(id(a) == id(b))

a, b = 999, 999
print(id(a) == id(b))

a, b = 2**10, 2**10
print(id(a) == id(b))

a,b = 2**100, 2**100
print(id(a) == id(b))

a, b = 1267650600228229401496703205376,1267650600228229401496703205376  

print(id(a) == id(b))

print('===========')

a=200
b=200
print(id(a) == id(b))

a=999
b=999
print(id(a) == id(b))

a = 2**10
b = 2**10
print(id(a) == id(b))

a = 2**100
b = 2**100
print(id(a) == id(b))

a = 1267650600228229401496703205376
b = 1267650600228229401496703205376
print(id(a) == id(b))
bvuwiixz

bvuwiixz1#

这真的很有趣,我可以尝试自己我会说:
0和1(可能还有其他一些)被存储到固定的内存地址,因此它们获得固定的ID。即使对它们进行计算也会保留ID(0100,1100)
数学运算中的其他数字会得到它们自己的ID,如2100、3100等。
所以这应该是一个简单/便宜的方法来处理0和1和/或小数字
我做了这个练习:

for i in range(0,300):
  a=2**i
  b=2**i
  print(f"{i} - True" if id(a) == id(b) else f"{i} - False")

结果很有趣

0 - True
1 - True
2 - True
3 - True
4 - True
5 - True
6 - True
7 - True
8 - True
9 - False
10 - False
11 - False
12 - False
13 - False
14 - False
15 - False
16 - False
17 - False
the rest is false.....

我增加了基数,基数越大,它就越早开始给变量分配不同的ID,所以某种程度上它和数字的大小有关
所以我还没有答案,但我很高兴能发现到底发生了什么!

相关问题