我在python 2.7.6 REPL中玩,并遇到了这种行为.
>>> x = -10
>>> y = -10
>>> x is y
False
>>> x, y = [-10, -10]
>>> x is y
True
Run Code Online (Sandbox Code Playgroud)
看起来,析构化赋值为等效值返回相同的引用.为什么是这样?
我对Python一无所知,但我很好奇.
首先,在分配数组时也会发生这种情况:
x = [-10,-10]
x[0] is x[1] # True
Run Code Online (Sandbox Code Playgroud)
它也发生在字符串中,它们是不可变的.
x = ['foo', 'foo']
x[0] is x[1] # True
Run Code Online (Sandbox Code Playgroud)
拆卸第一个功能:
0 LOAD_CONST 1 (-10)
3 LOAD_CONST 1 (-10)
6 BUILD_LIST 2
9 STORE_FAST 0 (x)
Run Code Online (Sandbox Code Playgroud)
该LOAD_CONST (consti)运算常数推co_consts[consti]到堆栈中.但是这里的两个操作都有consti=1,所以同一个对象被推到堆栈两次.如果数组中的数字不同,它将反汇编为:
0 LOAD_CONST 1 (-10)
3 LOAD_CONST 2 (-20)
6 BUILD_LIST 2
9 STORE_FAST 0 (x)
Run Code Online (Sandbox Code Playgroud)
这里,推送索引1和2的常量.
co_consts是Python脚本使用的常量元组.显然,具有相同值的文字只存储一次.
至于为什么'正常'赋值有效 - 你正在使用REPL,所以我假设每行都是单独编译的.如果你放
x = -10
y = -10
print(x is y)
Run Code Online (Sandbox Code Playgroud)
进入测试脚本,你会得到True.所以正常的赋值和析构赋值在这方面都是一样的:)
会发生什么是交互式Python解释器分别编译每个语句.编译不仅产生字节码,还为任何内置的不可变类型(包括整数)产生常量.这些常量与代码对象一起存储为co_consts属性.
您x = -10与y = -10作业分开编译,最终得到完全独立的co_consts结构.x, y = [-10, -10]另一方面,您的可迭代赋值是单个赋值语句,一次传递给编译器,因此编译器可以重用常量.
你可以将简单的语句(如赋值)放在一行上,并在它们之间加一个分号,此时,在Python 2.7中,你-10再次得到同一个对象:
>>> x = -10; y = -10
>>> x is y
True
Run Code Online (Sandbox Code Playgroud)
这里我们再次编译一个语句,因此编译器可以决定它只需要一个对象来表示-10值:
>>> compile('x = -10; y = -10', '', 'single').co_consts
(-10, None)
Run Code Online (Sandbox Code Playgroud)
'single'是交互式解释器使用的编译模式.编译后的字节码-10从这些常量中加载值.
如果你把所有东西放在一个函数中,你会得到同样的东西,编译成一个复合语句:
>>> def foo():
... x = -10
... y = -10
... return x is y
...
>>> foo()
True
>>> foo.__code__.co_consts
(None, -10)
Run Code Online (Sandbox Code Playgroud)
模块也在一次传递中编译,因此模块中的全局变量可以共享常量.
所有这些都是一个实现细节.你永远不应该指望这一点.
例如,在Python 3.6中,一元减运算符是单独处理的(而不是-10被视为单个整数文字),并且-10在窥孔优化期间在常量折叠之后达到该值.这可以让您获得两个单独的-10值:
>>> import sys
>>> sys.version_info
sys.version_info(major=3, minor=6, micro=3, releaselevel='final', serial=0)
>>> compile('x = -10; y = -10', '', 'single').co_consts
(10, None, -10, -10)
Run Code Online (Sandbox Code Playgroud)
其他Python实现(PyPy,Jython,IronPython等)可以再次以不同的方式自由处理常量.
| 归档时间: |
|
| 查看次数: |
2724 次 |
| 最近记录: |