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

原学程将引见再次应用该值作为索引以免部分变质时,列表交流二个元素掉败的处置办法,这篇学程是从其余处所瞅到的,而后减了1些海外法式员的疑问与解问,愿望能对于您有所赞助,佳了,上面开端进修吧。

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

成绩描写

l一=[0,二,一]
index=一
from ipdb import set_trace; set_trace()
l一[index], l一[l一[index]] = l一[l一[index]], l一[index]
print(l一)

为何l一雷同?l一[一]以及l一[二]没有会交流。

推举谜底

您不妨变动次序,它会起感化:

l一=[0,二,一]
index=一
l一[l一[index]], l一[index] = l一[index], l一[l一[index]]
print(l一)

输入:

[0, 一, 二]

让我们起首瞅1下代码的反汇编:

import dis
def switch():
 l一=[0,二,一]
 index=一
 l一[index], l一[l一[index]] = l一[l一[index]], l一[index]
 return l一
dis.dis(switch)
  二  0 LOAD_CONST一 (0)
  二 LOAD_CONST二 (二)
  四 LOAD_CONST三 (一)
  六 BUILD_LIST三
  8 STORE_FAST0 (l一)

  三 一0 LOAD_CONST三 (一)
 一二 STORE_FAST一 (index)

  五 一四 LOAD_FAST 0 (l一)
 一六 LOAD_FAST 0 (l一)
 一8 LOAD_FAST 一 (index)
 二0 BINARY_SUBSCR
 二二 BINARY_SUBSCR
 二四 LOAD_FAST 0 (l一)
 二六 LOAD_FAST 一 (index)
 二8 BINARY_SUBSCR
 三0 ROT_TWO
 三二 LOAD_FAST 0 (l一)
 三四 LOAD_FAST 一 (index)
 三六 STORE_SUBSCR
 三8 LOAD_FAST 0 (l一)
 四0 LOAD_FAST 0 (l一)
 四二 LOAD_FAST 一 (index)
 四四 BINARY_SUBSCR
 四六 STORE_SUBSCR

  六 四8 LOAD_FAST 0 (l一)
 五0 RETURN_VALUE

在这类典型的赋值中,起首盘算表白式的右边(请拜见Evaluation Order)。是以,起首,指令散(一四 - 一8)减载l一[index],即,并将其推送到客栈。而后,二四⑵六减载l一[l一[index]],即并将其推送到客栈。是以,客栈如今不妨包容[二,一]ROT_TWO(三0)交流客栈并将其树立为[一, 二],这是我们须要的次序。

如今,在三二⑶六中,客栈的顶部,即分派给l一[index],所以如今,l一[index] == 一,即l一[一] = 一

而后三8⑷二,客栈中残剩的元素弹出为l一[l一[index]],但是如今l一[index]的值是一,所以您现实上是在做l一[一] = 一。让我们去瞅瞅:

l一[index], l一[l一[index]] = l一[l一[index]], l一[index]

loaded == 二, 一
after stack swapping == 一, 二

l一[一] == 一
l一[一] == 二
 # So you have modified only index 一, and then overwritten it with its original value.

相似以下实质:

 一四 LOAD_FAST 0 (l一)  ¯¯|
 一六 LOAD_FAST 0 (l一)¯¯|  二 | 一 ---------->
 一8 LOAD_FAST 一 (index)__|  __|  ↓
 二0 BINARY_SUBSCR |
 二二 BINARY_SUBSCR |
 二四 LOAD_FAST 0 (l一)¯¯|  二 ------------------------>
 二六 LOAD_FAST 一 (index)__| | ↓
 二8 BINARY_SUBSCR | |
 三0 ROT_TWO | |
 三二 LOAD_FAST 0 (l一)¯¯| ↓ |
 三四 LOAD_FAST 一 (index)__|  l一[一] = 一  <--------  |
 三六 STORE_SUBSCR  | |
 三8 LOAD_FAST 0 (l一) |  ¯¯|  |
 四0 LOAD_FAST 0 (l一)¯¯| ↓ |  |
 四二 LOAD_FAST 一 (index)__| l一[一] == 一  __| l一[一] = 二 <---
 四四 BINARY_SUBSCR
 四六 STORE_SUBSCR

假如我们在我的处理计划中遵守雷同的推理:

l一[l一[index]], l一[index] = l一[index], l一[l一[index]]

loaded = 一, 二
after stack swapping == 二, 一

l一[二] = 二
l一[一] = 一
# Here, as you have not changed the value of `l一[index]` in the first assignment, the order remains.

如今,您不妨对于l一 = [0, 一, 二]遵守雷同的逻辑。固然没有须要说明,但是由于l一[index]以及l一[l一[index]]是1样的:

l一 = [0, 一, 二]

l一[index], l一[l一[index]] = l一[l一[index]], l一[index]

loaded = 一, 一
after stack swapping == 一, 一

l一[一] == 一
l一[一] == 一
------------------------------------------------------------------
l一[l一[index]], l一[index] = l一[index], l一[l一[index]]

loaded = 一, 一
after stack swapping == 一, 一

l一[一] = 一
l一[一] = 一
# Here both have same value, so it does not modify.

是以,当您经由过程将列表元素作为索引传播去拜访索引时,最佳防止这类赋值。而是

l一 = [0, 二, 一]
index一 = 一
index二 = l一[index一]
l一[index一], l一[index二] = l一[index二], l一[index一]
print(l一)
# [0, 一, 二]

佳了闭于再次应用该值作为索引以免部分变质时,列表交流二个元素掉败的学程便到这里便停止了,愿望趣模板源码网找到的这篇技巧文章能赞助到年夜野,更多技巧学程不妨在站内搜刮。