我写了三行相同的代码并得到不同的结果,首先我在一个交互式 shell 中运行它:
>>> a = 10000
>>> b = 10000
>>> a is b
False
>>> a = 10000; b = 10000; a is b
True
然后我有一个 Python 文件,其中包含:
a = 10000
b = 10000
print a is b
我运行它并得到
True
我的 Python 环境:
Python 2.7.5 (default, Mar 9 2014, 22:15:05)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
这里发生了什么?大家都在说编译,有谁知道交互式shell是如何编译和运行这几行代码的?
最佳答案
如果您将其中任何一个放入函数,它也会评估 True
。发生的事情是 Python 制作了一个在将函数编译为字节码时使用的常量列表,并且相等的常量将被“折叠”为一个值,该值被加载两次。看起来交互式解释器在编译一行代码时也做同样的事情*
所以这里是使用 dis
获得的这些函数之一的字节码——除了行号之外,这两种方法实际上都是相同的,所以我不会在这里复制两者。
2 0 LOAD_CONST 1 (10000)
3 STORE_FAST 0 (a)
6 LOAD_CONST 1 (10000)
9 STORE_FAST 1 (b)
12 LOAD_FAST 0 (a)
15 LOAD_FAST 1 (b)
18 COMPARE_OP 8 (is)
21 RETURN_VALUE
这是为了:
def func():
a = 10000; b = 10000; return a is b
from dis import dis
dis(func)
请注意,两条
LOAD_CONST
行具有相同的参数。这是对 func.__code__.co_consts
中的索引的引用,它是一个元组。该元组的元素 1 是 int 对象 10000
。为了完整起见,如果您对其进行
a = 10000; b = 10000; a is b
,这里是原始单行 compile()
的反汇编: 1 0 LOAD_CONST 0 (10000)
3 STORE_NAME 0 (a)
6 LOAD_CONST 0 (10000)
9 STORE_NAME 1 (b)
12 LOAD_NAME 0 (a)
15 LOAD_NAME 1 (b)
18 COMPARE_OP 8 (is)
21 POP_TOP
22 LOAD_CONST 1 (None)
25 RETURN_VALUE
除了行号/常量号、
NAME
与 FAST
以及从 POP_TOP
开始的结尾之外,它从根本上是相似的。而如果您在单独的行上分配值,则不会使用常量执行此操作,因此每次都会创建一个新的 int 对象。*为了增加一点吸引力,如果我将单行版本放入我的 IPython 笔记本中,
a is b
就是 False
。关于python - CPython IntObject 上奇怪的 id 结果,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25281892/