再次使用該值作為索引以避免局部變量時,列表交換兩個元素失敗 [英] list swap two elements failed when using the value as index again to avoid a local variable

查看:0
本文介紹了再次使用該值作為索引以避免局部變量時,列表交換兩個元素失敗的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

問題描述

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屋!

查看全文
登錄 關閉
掃碼關注1秒登錄
發送“驗證碼”獲取 | 15天全站免登陸
亚洲AV无码国产精品