我在文章中找到了作业a = a[1:] = [2]
。我在python3和python2中尝试过它;这一切都有效,但我不明白它是如何工作的 。 =
这里不像C; C从右到左处理=
。 python如何处理=
运算符?
答案 0 :(得分:15)
每the language docs on assignment:
赋值语句计算表达式列表(请记住,这可以是单个表达式或以逗号分隔的列表,后者产生元组)并将单个结果对象从左到右分配给每个目标列表。
在这种情况下,a = a[1:] = [2]
有一个表达式列表[2]
,以及两个"目标列表",a
和a[1:]
,其中{{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
对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
答案 1 :(得分:7)
我理解这些作业的方式是,这相当于
temp = [2]
a = temp
a[1:] = temp
[2, 2]
的结果值与此解释一致。