This question already has an answer here:
Python Assignment Operator Precedence - (a, b) = a[b] = {}, 5
(1个答案)
2年前关闭。
我在文章中找到了作业
(反汇编的最后两行可以忽略,
需要注意的重要部分是,当您执行
因此,当您这样做时:
它对包含
最终结果与完成后的结果相同:
但避免使用
需要明确的是,反汇编注释如下:
制作列表
复制对
执行存储到
执行存储到
(1个答案)
2年前关闭。
我在文章中找到了作业
a = a[1:] = [2]
。我在python3和python2中尝试过;都可以,但是我不知道它是如何工作的。此处的=
与C语言不同; C从右到左处理=
。 python如何处理=
运算符? 最佳答案
每the language docs on assignment:
在这种情况下,a = a[1:] = [2]
具有一个表达式列表[2]
和两个“目标列表”,a
和a[1:]
,其中a
是最左侧的“目标列表”。
您可以通过查看反汇编来了解其行为:
>>> import dis
>>> dis.dis('a = a[1:] = [2]')
1 0 LOAD_CONST 0 (2)
2 BUILD_LIST 1
4 DUP_TOP
6 STORE_NAME 0 (a)
8 LOAD_NAME 0 (a)
10 LOAD_CONST 1 (1)
12 LOAD_CONST 2 (None)
14 BUILD_SLICE 2
16 STORE_SUBSCR
18 LOAD_CONST 2 (None)
20 RETURN_VALUE
(反汇编的最后两行可以忽略,
dis
正在使用函数包装器来反汇编字符串)需要注意的重要部分是,当您执行
x = y = some_val
时,some_val
被加载到堆栈上(在这种情况下是LOAD_CONST
和BUILD_LIST
),然后堆栈条目被复制并从左到右分配给给定的目标。因此,当您这样做时:
a = a[1:] = [2]
它对包含
list
的全新2
进行了两次引用,并且第一个 Action 是STORE
,其中之一是对a
的引用。接下来,它存储对a[1:]
的第二个引用,但是由于切片分配会更改a
本身,因此必须再次加载a
,这将得到刚刚存储的list
。幸运的是,list
可以抵抗自我分配,否则我们将遇到问题(它将永远读取它刚刚添加的值并添加到末尾,直到我们耗尽内存并崩溃为止);实际上,它的行为就像是分配了[2]
的副本以替换从索引1开始的任何和所有元素一样。最终结果与完成后的结果相同:
_ = [2]
a = _
a[1:] = _
但避免使用
_
名称。需要明确的是,反汇编注释如下:
制作列表
[2]
: 1 0 LOAD_CONST 0 (2)
2 BUILD_LIST 1
复制对
[2]
的引用: 4 DUP_TOP
执行存储到
a
: 6 STORE_NAME 0 (a)
执行存储到
a[1:]
: 8 LOAD_NAME 0 (a)
10 LOAD_CONST 1 (1)
12 LOAD_CONST 2 (None)
14 BUILD_SLICE 2
16 STORE_SUBSCR