【问题标题】:Why same id() for two distinct variables with the same float value in Python 3.6.x/ 2.7.x?为什么在 Python 3.6.x/2.7.x 中两个具有相同浮点值的不同变量的 id() 相同?
【发布时间】:2018-07-05 17:35:01
【问题描述】:

试试:

f1 = 2.0
f2 = 2.0
print (id(f1), id(f2), id(f1) == id(f2))
f1 = 2.0
f2 = 2.00
print (id(f1), id(f2), id(f1) == id(f2))
f1 = 2.0
f2 = 2.0 + 0
print (id(f1), id(f2), id(f1) == id(f2))

结果 Python 3.6.2 (v3.6.2:5fd33b5, Jul 8 2017, 04:14:34) [MSC v.1900 32 bit (Intel)] on win32:

28901952 28901952 True
28901952 28901952 True
28901952 28903248 False

结果 Python 3.6.1(v3.6.1:69c0db5,2017 年 3 月 21 日,18:41:36)[MSC v.1900 64 位(AMD64)]:

408502020664 408502020664 True
408502020664 408502020664 True
408502020664 408502019104 False

结果 ('2.7.13 ('2.7.13 (default, Jun 26 2017, 10:20:05)) \n[GCC 7.1.1 20170622 (Red Hat 7.1.1-3)]', sys.version_info(major=2,次要=7,微型=13,发布级别='最终',串行=0)):

(140026865510064, 140026865510064, True)
(140026865510064, 140026865510064, True)
(140026865510064, 140026865509968, False) 

为什么浮点数的 id 相同? 幕后会发生什么(比如在 -5 到 256 范围内保留的整数对象?)?

【问题讨论】:

  • 你看过字节码了吗?我猜 2.0 会变成一个浮点常量,然后所有硬编码的 2.0 都会引用它。您可以尝试询问用户输入并输入 2.0,然后我敢打赌它们是不同的 id。
  • 这显然是依赖于实现的,我的机器上带有 Py 2 和 Py 3 的所有 3 个都得到 False
  • @Coldspeed 不完全是一个骗子,如果他们询问实施细节
  • 所以用 python3 标记
  • 而且没有重复。

标签: python python-3.x


【解决方案1】:

这只发生在代码被编译/翻译成字节码,而不是在 REPL 中解释的情况下(尽管一些解释器 my 也显示这种行为)。考虑以下函数:

def fn():
    f1 = 2.0
    f2 = 2.0
    return f1, f2

当这个函数被编译成字节码时,文字2.0 成为函数fn 的局部常量。 Python 足够聪明,可以看到第一个 2.0 与第二个 2.0 相同,因此它只存储一次。在运行时,该函数将从函数的co_consts 中加载常量并将其分别存储在f1f2 中。这就是f1f2 具有相同id 的原因:它们是对相同常量的引用。

>>> f1, f2 = fn()
>>> f1 is fn.__code__.co_consts[1]
True
>>> f2 is fn.__code__.co_consts[1]
True

2.0 + 0 没有相同的id,因为原始常量2.0 是不可变的,Python 不只是跳过(否则是幂等的)加法。因此,相加的结果必须是一个新对象,因此是一个不同的id

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-19
    • 1970-01-01
    • 2020-12-02
    • 2016-01-03
    • 2013-09-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多