【发布时间】:2016-12-14 13:22:15
【问题描述】:
我在对模块进行单元测试时遇到了一个令人困惑的问题。该模块实际上是在转换值,我想比较这些值。
与== 和is 相比存在差异(部分,我要注意差异)
>>> 0.0 is 0.0
True # as expected
>>> float(0.0) is 0.0
True # as expected
到目前为止,正如预期的那样,但这是我的“问题”:
>>> float(0) is 0.0
False
>>> float(0) is float(0)
False
为什么?至少最后一个让我很困惑。 float(0) 和 float(0.0) 的内部表示应该相等。与== 的比较按预期工作。
【问题讨论】:
-
您的问题值得回答,但如果您在实际代码中遇到此问题,则代码可能有误,应予以修复。 (几乎)没有理由以这种方式测试浮点数之间的引用身份。
-
奇怪的是,虽然我可以重现这一点,但
id(0.0)、id(float(0.0))和id(float(0))都返回相同的值。 ...也就是说,如果我在交互式 shell 中一个接一个地执行这些值,那么值是相同的,但是如果我执行id(float(0.0)), id(float(0))(作为一个元组),那么 ID 就会不同。有什么解释吗? -
@Elazar:感谢添加 cpython 标记,因为它似乎与 cpython 非常相关,您不应该依赖任何东西(正如您已经提到的)
-
@tobias_k:两个原因:代码中的不可变文字与代码对象一起存储为常量(因此
0.0 is 0.0只生成一个可重用的对象),Python 重用内存(因此id(0.0)后跟另一个id(someobject)可以很容易地产生相同的 id,因为前一个已经被垃圾回收了)并且产生一个元组不能重用内存位置,因为你仍然需要 all 对象作为其中的一部分元组。
标签: python python-2.7 python-3.x floating-point python-internals