$ python2
Python 2.7.8 (default, Sep 24 2014, 18:26:21)
>>> a = 257
>>> b = 257
>>> a is b
False
$ python3
Python 3.4.2 (default, Oct 8 2014, 13:44:52)
>>> a = 257
>>> b = 257
>>> a is b
False
是吗?在
本例中的每一行都是一个单独的编译单元,并且
重复数据消除无法在它们之间进行。它的工作原理与
compile a = 257
run a = 257
compile b = 257
run b = 257
compile a is b
run a is b
因此,这些代码对象都将具有唯一的常量缓存。
这意味着如果删除换行符,is将返回True:
>>> a = 257; b = 257
>>> a is b
True
实际上,这两个Python版本都是如此。事实上,这就是为什么
>>> a, b = 257, 257
>>> a is b
True
也返回True;这不是因为解包的任何属性;它们
放在同一个编译单元。在
对于没有正确折叠的版本,返回False;filmor links to Ideone,这表明在2.7.3和3.2.3上失败。在这些版本中,创建的元组不会与其他常量共享它们的项:
import dis
def f():
a, b = 257, 257
print(a is b)
print(f.__code__.co_consts)
#>>> (None, 257, (257, 257))
n = f.__code__.co_consts[1]
n1 = f.__code__.co_consts[2][0]
n2 = f.__code__.co_consts[2][1]
print(id(n), id(n1), id(n2))
#>>> (148384292, 148384304, 148384496)
这种行为至少在一定程度上与解释器如何进行常量折叠有关 以及REPL如何执行代码。在
首先,请记住CPython首先编译代码(到AST,然后编译字节码)。然后评估 字节码。在编译期间,脚本查找不可变的对象并将其缓存。它 还可以对它们进行重复数据消除。所以如果它看到
它将针对同一对象存储a和b:
^{pr2}$注意
LOAD_CONST 1
。1
是co_consts
的索引:所以这两个加载相同的
257
。为什么不出现这种情况:是吗?在
本例中的每一行都是一个单独的编译单元,并且 重复数据消除无法在它们之间进行。它的工作原理与
因此,这些代码对象都将具有唯一的常量缓存。 这意味着如果删除换行符,
is
将返回True
:实际上,这两个Python版本都是如此。事实上,这就是为什么
也返回
True
;这不是因为解包的任何属性;它们 放在同一个编译单元。在对于没有正确折叠的版本,返回
False
;filmor links to Ideone,这表明在2.7.3和3.2.3上失败。在这些版本中,创建的元组不会与其他常量共享它们的项:不过,这并不是关于对象解包方式的改变,而是对象在
co_consts
中的存储方式的改变。在我认为这实际上是偶然的,因为我无法用Python3.2重现这种行为。在
这个问题http://bugs.python.org/issue11244引入了一个
CONST_STACK
来解决带有负数的常量元组没有被优化的问题(看看针对peephole.c
的补丁,其中包含Python的优化程序运行)。在这似乎也导致了既定的行为。还在调查中:)
相关问题 更多 >
编程相关推荐