python交换和赋值

Gab*_*iel 4 python swap

通常,我们A[i], A[j] = A[j], A[i]用来交换.

这有时可能无效.例如,

A=[1, 2]
A[0], A[A[0]] = A[A[0]], A[0]
Run Code Online (Sandbox Code Playgroud)

将失败.为什么会失败以及如何解释赋值?

Ned*_*der 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
Run Code Online (Sandbox Code Playgroud)

这样工作如下:

  • 指令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]
Run Code Online (Sandbox Code Playgroud)