Python 为什么id函数在使用整数和浮点时表现不同?

Python 为什么id函数在使用整数和浮点时表现不同?,python,python-2.7,Python,Python 2.7,我尝试了下面的代码,它给了我不同的输出 >>> foo1 = 4 >>> foo2 = 2+2 >>> id(foo1) 37740064L >>> id(foo2) 37740064L >>> foo1 = 4.3 >>> foo2 = 1.3+3.0 >>> id(foo1) 37801304L >>> id(foo2) 37801232L >

我尝试了下面的代码,它给了我不同的输出

>>> foo1 = 4
>>> foo2 = 2+2
>>> id(foo1)
37740064L
>>> id(foo2)
37740064L

>>> foo1 = 4.3
>>> foo2 = 1.3+3.0
>>> id(foo1)
37801304L
>>> id(foo2)
37801232L
>>>

我正在使用python 2.7.2。为什么id函数在浮点数的情况下返回不同的值,而在整数的情况下返回相同的值?

这是因为数值常量中
id
的结果是实现定义的

在Python2.7.2 IIRC中,问题是编译器将一些有用的整数常量构建为单例(从-1到100左右)。其基本原理是,这些数字被频繁使用,以至于在每次需要时动态分配它们是没有意义的,它们只是被重用

但是,这种恒定的单例优化对于
float
值没有用处,除了0.0之外,它们太多了!因此,每次需要一个新的
float
值时,它都会被分配,并获得一个不同的id


要获得更深入的见解,请阅读源代码!源于Python3,但思想是一样的:查找
小整数数组。

id
从来都不是可预测的,即使是整数也是如此。对于非常低的整数2和4,您恰好命中了小整数缓存。试试这个:

>>> a = 12345
>>> b = 12345
>>> id(a)
33525888
>>> id(b)
33525852
>>>

除了上述(非常真实)的原因外,您是否首先验证了
foo1==foo2
?在处理浮点值时,很容易出现差异…

对于浮点数,1.0+3.3==4.3并不总是真的(在Python或其他语言中)。具有相同值的可变对象也可以具有不同的ID。

对于预期经常使用的小整数和字符串,Python使用内部内存优化。因为Python中的任何变量都是对内存对象的引用,所以Python只将如此小的值放入内存一次。然后,只要将相同的值分配给任何其他变量,它就会使该变量指向已保存在内存中的对象。这适用于字符串和整数,因为它们是不可变的,如果变量值发生变化,实际上是该变量使用的引用发生了变化,内存中具有原始值的对象本身不会受到影响

这就是为什么变量foo1和foo2在第一种情况下引用内存中值为4的同一整数对象,因此ID是相同的

首先,浮点数不是“小”的,其次,根据计算结果,内存中相同的4.3可能会保留为4.3123456789和4.31239874654(只需举例说明)。因此,这两个值是两个不同的对象,但在计算和显示有意义的部分时,它们看起来是相同的,即4.3(事实上,对于同一个有意义的浮点数,内存中显然有更多可能的值)。因此,在内存中重用同一个浮点数对象是有问题的,毕竟不值得

这就是为什么在第二种情况下,foo1和foo2引用内存中不同的浮点对象,因此具有不同的id

有关如何在内存中保留浮点数的更多详细信息,请参见:

另外,在Oracle文档中有一篇关于浮点数的大文章


@josliber,我按照您的建议在重新发布之前编辑了答案。

在这种情况下,包含变量的浮点值可能包含相同的数据,但背后的原因是数学规则。 在点和剩余值被忽略之后,只考虑两个值。 因此,我们得到了包含变量的相同数据的两个不同地址。 要解决此错误,可以使用round()方法


这可以显示两者都有相同的地址,因为在print(round(x,2))方法和print(round(y,2))方法中,只取点后的两位数字。

0.0
没有被缓存,尽管你并没有暗示我只是想说so@jamylak:没有,我刚刚看到代码,但我仍然认为这可能是一个好主意…只是尝试了一下,因此接受了你的解决方案。
>>>>aList=['ammonium',83,85,'lady']>>>>>>>>>>>aList['ammonium',83,85,'lady'>>>>>>>>>aList[2]=aList[2]+1>>aList[3]='stero'>>>>aList['ammonium',83,86,'stero'>>>>>>>>id(aList)135443480>>>>>>>aList.append('haudy')>>>>aList.append(aList[2]+1)>>>aList['amino',83,86,'stereo',haudy',87]>>>>id(aList)135443480
y=3.1254
x = 3.1254
print(round(x,2))
print(round(y,2))
print(id(x)==id(y))