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

时间:2018-01-26 11:20:08

标签: python python-3.x

尝试:

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,2017年7月8日,04:14:34)[MSC v.1900 32位(英特尔)]在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 bit(AMD64)]:

408502020664 408502020664 True
408502020664 408502020664 True
408502020664 408502019104 False

结果('2.7.13(默认,2017年6月26日,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?)?

1 个答案:

答案 0 :(得分: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