This question already has an answer here:
Python Assignment Operator Precedence - (a, b) = a[b] = {}, 5

(1个答案)


2年前关闭。




我在文章中找到了作业a = a[1:] = [2]。我在python3和python2中尝试过;都可以,但是我不知道它是如何工作的。此处的=与C语言不同; C从右到左处理=。 python如何处理=运算符?

最佳答案

the language docs on assignment:



在这种情况下,a = a[1:] = [2]具有一个表达式列表[2]和两个“目标列表”,aa[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_CONSTBUILD_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

10-07 19:28
查看更多