为什么函数的行为与整数和浮点数不同?

时间:2013-04-14 08:05:08

标签: 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
>>>

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

6 个答案:

答案 0 :(得分:5)

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

在你的情况下,Python 2.7.2,IIRC,问题是编译器构建一些有用的整数常量作为单例(从-1到100左右)。理由是这些数字经常被使用,每次需要时动态分配它们是没有意义的,它们只是被重用。

但是这个常数单例优化对于float值没有用,除了0.0以外,它们太多了!因此,每次需要新的float值时,都会对其进行分配,并获得不同的ID。

要获得更深入的洞察力,请阅读来源! This file来自Python3,但想法是一样的:查找small_ints数组。

答案 1 :(得分:1)

id永远不可预测,甚至不是整数。如果整数 2 4 都很低,那么你恰好碰到了小整数缓存。试试这个:

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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

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

首先,浮点数不是“小”,其次,内存中相同的4.3可能会保留为4.3123456789和4.31239874654(只是示例数字来解释)。所以这两个值是两个不同的对象,但是在计算和显示期间,有意义的部分看起来是相同的,即4.3(事实上,对于相同的有意义的浮点数,内存中显然有更多可能的值)。因此,在内存中重用相同的浮点数对象是有问题的,毕竟不值得。

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

详细了解浮点数如何保留在内存中:

http://floating-point-gui.de/

http://docs.python.org/2/tutorial/floatingpoint.html

此外,还有一篇关于Oracle docs浮点数的大文章。

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

答案 5 :(得分:0)

在那种情况下,包含变量的float值可能包含相同的数据,但其背后的原因是数学规则。 该点之后仅考虑两个值,其余的则被忽略。 因此我们得到了包含变量的同一数据的两个不同地址。 要解决此错误,我们可以使用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))方法中,点之后只有两位数字。