再次使用該值作為索引以避免局部變量時,列表交換兩個元素失敗 [英] list swap two elements failed when using the value as index again to avoid a local variable
本文介紹了再次使用該值作為索引以避免局部變量時,列表交換兩個元素失敗的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!
問題描述
l1=[0,2,1]
index=1
from ipdb import set_trace; set_trace()
l1[index], l1[l1[index]] = l1[l1[index]], l1[index]
print(l1)
為什么l1
相同?l1[1]
和l1[2]
不會交換。
推薦答案
您可以更改順序,它會起作用:
l1=[0,2,1]
index=1
l1[l1[index]], l1[index] = l1[index], l1[l1[index]]
print(l1)
輸出:
[0, 1, 2]
讓我們首先看一下代碼的反匯編:
import dis
def switch():
l1=[0,2,1]
index=1
l1[index], l1[l1[index]] = l1[l1[index]], l1[index]
return l1
dis.dis(switch)
2 0 LOAD_CONST 1 (0)
2 LOAD_CONST 2 (2)
4 LOAD_CONST 3 (1)
6 BUILD_LIST 3
8 STORE_FAST 0 (l1)
3 10 LOAD_CONST 3 (1)
12 STORE_FAST 1 (index)
5 14 LOAD_FAST 0 (l1)
16 LOAD_FAST 0 (l1)
18 LOAD_FAST 1 (index)
20 BINARY_SUBSCR
22 BINARY_SUBSCR
24 LOAD_FAST 0 (l1)
26 LOAD_FAST 1 (index)
28 BINARY_SUBSCR
30 ROT_TWO
32 LOAD_FAST 0 (l1)
34 LOAD_FAST 1 (index)
36 STORE_SUBSCR
38 LOAD_FAST 0 (l1)
40 LOAD_FAST 0 (l1)
42 LOAD_FAST 1 (index)
44 BINARY_SUBSCR
46 STORE_SUBSCR
6 48 LOAD_FAST 0 (l1)
50 RETURN_VALUE
在這種類型的賦值中,首先計算表達式的右側(請參見Evaluation Order)。因此,首先,指令集(14 - 18)
加載l1[index]
,即1
,并將其推送到堆棧。然后,24-26
加載l1[l1[index]]
,即2
并將其推送到堆棧。因此,堆?,F在可以容納[2,1]
。ROT_TWO
(30)交換堆棧并將其設置為[1, 2]
,這是我們需要的順序。
現在,在32-36中,堆棧的頂部,即1
分配給l1[index]
,所以現在,l1[index] == 1
,即l1[1] = 1
。
然后38-42,堆棧中剩余的元素2
彈出為l1[l1[index]]
,但現在l1[index]
的值是1,所以您實際上是在做l1[1] = 1
。讓我們來看看:
l1[index], l1[l1[index]] = l1[l1[index]], l1[index]
loaded == 2, 1
after stack swapping == 1, 2
l1[1] == 1
l1[1] == 2
# So you have modified only index 1, and then overwritten it with its original value.
類似以下內容:
14 LOAD_FAST 0 (l1) ˉˉ|
16 LOAD_FAST 0 (l1) ˉˉ| 2 | 1 ---------->
18 LOAD_FAST 1 (index)__| __| ↓
20 BINARY_SUBSCR |
22 BINARY_SUBSCR |
24 LOAD_FAST 0 (l1) ˉˉ| 2 ------------------------>
26 LOAD_FAST 1 (index)__| | ↓
28 BINARY_SUBSCR | |
30 ROT_TWO | |
32 LOAD_FAST 0 (l1) ˉˉ| ↓ |
34 LOAD_FAST 1 (index)__| l1[1] = 1 <-------- |
36 STORE_SUBSCR | |
38 LOAD_FAST 0 (l1) | ˉˉ| |
40 LOAD_FAST 0 (l1) ˉˉ| ↓ | |
42 LOAD_FAST 1 (index)__| l1[1] == 1 __| l1[1] = 2 <---
44 BINARY_SUBSCR
46 STORE_SUBSCR
如果我們在我的解決方案中遵循相同的推理:
l1[l1[index]], l1[index] = l1[index], l1[l1[index]]
loaded = 1, 2
after stack swapping == 2, 1
l1[2] = 2
l1[1] = 1
# Here, as you have not changed the value of `l1[index]` in the first assignment, the order remains.
現在,您可以對l1 = [0, 1, 2]
遵循相同的邏輯。雖然不需要解釋,但因為l1[index]
和l1[l1[index]]
是一樣的:
l1 = [0, 1, 2]
l1[index], l1[l1[index]] = l1[l1[index]], l1[index]
loaded = 1, 1
after stack swapping == 1, 1
l1[1] == 1
l1[1] == 1
------------------------------------------------------------------
l1[l1[index]], l1[index] = l1[index], l1[l1[index]]
loaded = 1, 1
after stack swapping == 1, 1
l1[1] = 1
l1[1] = 1
# Here both have same value, so it does not modify.
因此,當您通過將列表元素作為索引傳遞來訪問索引時,最好避免這種賦值。而是Explicit:
l1 = [0, 2, 1]
index1 = 1
index2 = l1[index1]
l1[index1], l1[index2] = l1[index2], l1[index1]
print(l1)
# [0, 1, 2]
這篇關于再次使用該值作為索引以避免局部變量時,列表交換兩個元素失敗的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持IT屋!
查看全文