为什么在Python 3.6.x/2.7.x中,两个具有相同浮点值的不同变量具有相同的id()?

3

尝试:

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)]在win32系统上:

28901952 28901952 True
28901952 28901952 True
28901952 28903248 False

Python 3.6.1的运行结果(版本号v3.6.1,发布日期为2017年3月21日,编译器为MSC v.1900 64位(AMD64)):

408502020664 408502020664 True
408502020664 408502020664 True
408502020664 408502019104 False

结果('2.7.13(默认,Jun 26 2017,10:20:05)\n [GCC 7.1.1 20170622(Red Hat 7.1.1-3)] ',sys.version_info(major = 2,minor = 7,micro = 13,releaselevel ='final',serial = 0)):

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

为什么浮点数的ID是相同的? 在背后发生了什么(类似于保留整数对象的范围为-5到256)?

2
你看过字节码吗?我猜2.0会变成一个浮点常量,然后所有硬编码的2.0都会引用它。你可以尝试请求用户输入并输入2.0,然后我敢打赌它们是不同的ID。 - dutt
@Coldspeed 不完全是重复,如果他们在询问实现细节。 - Chris_Rands
所以它被标记为Python3。 - V. E.
and it is no dup. - V. E.
好的,完成了 - 这是Python 3 - 请查看标签。 - V. E.
显示剩余9条评论
1个回答

1
只有当代码被编译/翻译成字节码时,才会发生这种情况,而不是在REPL中解释(尽管一些解释器也可能显示此行为)。考虑以下函数:
def fn():
    f1 = 2.0
    f2 = 2.0
    return f1, f2

当这个函数被编译成字节码时,文字“2.0”成为函数“fn”的本地常量。Python足够聪明,可以看到第一个“2.0”和第二个“2.0”是相同的,因此只存储一次。在运行时,函数将从函数的“co_consts”中加载常量,并分别将其存储在“f1”和“f2”中。这就是为什么“f1”和“f2”具有相同的“id”的原因:它们是对同一常量的引用。
>>> f1, f2 = fn()
>>> f1 is fn.__code__.co_consts[1]
True
>>> f2 is fn.__code__.co_consts[1]
True

2.0 + 0id与原始常量2.0不同,因为原始常量2.0是不可变的,Python不会跳过(本来是幂等的)加法运算。因此,加法的结果必须是一个新对象,因此具有不同的id


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接