Python交换和赋值

4
通常,我们使用A[i],A[j] = A[j],A[i]进行交换。
但有时可能不起作用。例如:
A=[1, 2]
A[0], A[A[0]] = A[A[0]], A[0]

将失败。它为什么会失败,以及分配如何被解释?
1个回答

6
让我们来看一下该语句的字节码:
>>> def f(A):
...   A[0], A[A[0]] = A[A[0]], A[0]
...
>>> dis.dis(f)
2           0 LOAD_FAST                0 (A)
            3 LOAD_FAST                0 (A)
            6 LOAD_CONST               1 (0)
            9 BINARY_SUBSCR
           10 BINARY_SUBSCR
           11 LOAD_FAST                0 (A)
           14 LOAD_CONST               1 (0)
           17 BINARY_SUBSCR
           18 ROT_TWO
           19 LOAD_FAST                0 (A)
           22 LOAD_CONST               1 (0)
           25 STORE_SUBSCR
           26 LOAD_FAST                0 (A)
           29 LOAD_FAST                0 (A)
           32 LOAD_CONST               1 (0)
           35 BINARY_SUBSCR
           36 STORE_SUBSCR
           37 LOAD_CONST               0 (None)
           40 RETURN_VALUE

这是运行方式:
  • 指令0-10将A[A[0]]推入值栈,因此它的值为2
  • 指令11-17将A[0]推入值栈,现在值栈为2, 1
  • 指令18交换它们,值栈变为1, 2
  • 指令19-25将顶部值(2)赋给A[0],值栈留下1
  • 指令26-36试图向A[A[0]]赋值,但A[0]现在是2,所以它试图赋值给A[2],这是一个IndexError。
简而言之,问题在于左侧的A[A[0]]直到赋值给A[0]之后才被计算。
作为解决方法,我建议:
A0 = A[0]
A[0], A[A0] = A[A0], A[0]

这并没有解释为什么前者语句是有效的,而后者不是。 - wvdz
@popovitsj 我加了一两句话。 - Ned Batchelder
A0,A [0],A [A0] = A [0],A [A [0]],A [0] 或 A0,A [0],A [A0] = A [0],A [A [0]],A0也可以。 - martineau
谢谢!所以当索引是可变对象时,需要一个tmp变量。 - Gabriel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接