我尝试了以下代码,它给了我不同的输出。
>>> 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 函数在浮点数的情况下返回不同的值但在整数的情况下返回相同的值?
我尝试了以下代码,它给了我不同的输出。
>>> 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
in 数字常量的结果是实现定义的。
在您的情况下,Python 2.7.2,IIRC,问题在于编译器构建了一些有用的整数常量作为单例(从 -1 到 100 左右)。基本原理是这些数字被频繁使用,以至于每次需要它们时动态分配它们是没有意义的,它们只是被重复使用。
但是那个恒定的单例优化对float
值没有用,除了可能 0.0 之外,它们太多了!因此,每次float
需要一个新值时都会分配它,并获得不同的 id。
如需更深入的了解,请阅读源代码!这个文件来自 Python3,但想法是一样的:查找small_ints
数组。
id
从来都不是真正可预测的,即使是整数也不行。使用低整数2和4,您恰好碰到了小整数缓存。尝试这个:
>>> a = 12345
>>> b = 12345
>>> id(a)
33525888
>>> id(b)
33525852
>>>
对于预计会经常使用的小整数和字符串,Python 使用内部内存优化。由于 Python 中的任何变量都是对内存对象的引用,因此 Python 只会将如此小的值放入内存中一次。然后,每当将相同的值分配给任何其他变量时,它都会使该变量指向已保存在内存中的对象。这适用于字符串和整数,因为它们是不可变的,如果变量值发生变化,实际上是该变量使用的引用发生了变化,内存中具有原始值的对象本身不会受到影响。
这就是为什么变量 foo1 和 foo2 在第一种情况下保持对内存中值为 4 的相同整数对象的引用,因此 id 是相同的。
首先,浮点数不是“小”,其次,根据计算,内存中的相同 4.3 可能会保留为 4.3123456789 和 4.31239874654(仅用于解释的示例数字)。所以这两个值是两个不同的对象,但是在计算和显示有意义的部分时看起来是一样的,即 4.3(事实上,对于相同的有意义的浮点数,内存中显然有更多可能的值)。所以在内存中重用同一个浮点数对象是有问题的,毕竟不值得。
这就是为什么在第二种情况下 foo1 和 foo2 在内存中引用不同的浮点对象,因此具有不同的 id。
查看有关浮点数如何保存在内存中的更多详细信息:
http://docs.python.org/2/tutorial/floatingpoint.html
此外,Oracle 文档中有一篇关于浮点数的大文章。
@josliber,我按照您的建议在重新发布之前编辑了答案。
对于浮点数,1.0+3.3 == 4.3 并不总是TRUE(在 Python 或其他语言中)。具有相同值的可变对象也可以具有不同的 ID。
除了提到的(并且非常真实的)原因之外,您是否foo1 == foo2
首先验证了?当您处理浮点值时,很容易出现差异......
在这种情况下,包含变量的浮点值可能包含相同的数据,但背后的原因是数学规则。唯一的两个值是在点之后考虑的,剩余的值被忽略。所以我们得到了包含变量的相同数据的两个不同地址。为了解决这个错误,我们可以使用 round() 方法。
y=3.1254
x = 3.1254
print(round(x,2))
print(round(y,2))
print(id(x)==id(y))
这可以显示两者具有相同的地址,因为在 print(round(x,2)) 方法和 print(round(y,2)) 方法中,点后只有两位数。