Python 再次使用值作为索引以避免局部变量时,列表交换两个元素失败

Python 再次使用值作为索引以避免局部变量时,列表交换两个元素失败,python,list,swap,Python,List,Swap,为什么l1是相同的l1[1]和l1[2]将不交换。您可以更改顺序,它将工作: 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=[0,2,1] index=1 l1[l1[index]], l1[index] = l1[index], l1[l1[index]] print(l1) 因此,

为什么
l1
是相同的
l1[1]
l1[2]
将不交换。

您可以更改顺序,它将工作:

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=[0,2,1]
index=1
l1[l1[index]], l1[index] = l1[index], l1[l1[index]]
print(l1)
因此,让我们首先看看代码的反汇编:

[0, 1, 2]
在这种类型的赋值中,首先计算表达式的右侧(请参见)。因此,首先,指令集
(14-18)
加载
l1[index]
,即
1
,并将其推送到堆栈中。然后,
24-26
加载
l1[l1[索引]]
,即
2
,并将其推送到堆栈中。因此堆栈现在保存
[2,1]
。交换堆栈并使其符合我们的要求

现在,在32-36中,堆栈的顶部,即
1
被分配给
l1[index]
,因此现在,
l1[index]==1
,即
l1[1]=1

然后38-42,堆栈中的剩余元素,即
2
被弹出到
l1[l1[index]]
,但是现在
l1[index]
的值是1,所以实际上是,
l1[1]=1
。让我们看看:

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
大概是这样的:

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.
现在,您可以对
l1=[0,1,2]
遵循相同的逻辑。尽管不需要解释,因为
l1[index]
l1[l1[index]]
都是相同的:

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[index]==l1[1]
l1[l1[index]==l1[l1[1]==l1[1]
回答好,+1回答好不是正确的答案,但我可以建议您的代码使用中间变量时可读性更好吗?
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[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.
l1 = [0, 2, 1]
index1 = 1
index2 = l1[index1]
l1[index1], l1[index2] = l1[index2], l1[index1]
print(l1)
# [0, 1, 2]