list swap two elements failed when using the value as index again to avoid a local variable(再次使用该值作为索引以避免局部变量时,列表交换两个元素失败)
本文介绍了再次使用该值作为索引以避免局部变量时,列表交换两个元素失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
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
并将其推送到堆栈。因此,堆栈现在可以容纳[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]
这篇关于再次使用该值作为索引以避免局部变量时,列表交换两个元素失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
沃梦达教程
本文标题为:再次使用该值作为索引以避免局部变量时,列表交换两个元素失败
基础教程推荐
猜你喜欢
- Python kivy 入口点 inflateRest2 无法定位 libpng16-16.dll 2022-01-01
- 何时使用 os.name、sys.platform 或 platform.system? 2022-01-01
- Dask.array.套用_沿_轴:由于额外的元素([1]),使用dask.array的每一行作为另一个函数的输入失败 2022-01-01
- 用于分类数据的跳跃记号标签 2022-01-01
- 筛选NumPy数组 2022-01-01
- 如何让 python 脚本监听来自另一个脚本的输入 2022-01-01
- 在 Python 中,如果我在一个“with"中返回.块,文件还会关闭吗? 2022-01-01
- 线程时出现 msgbox 错误,GUI 块 2022-01-01
- 如何在海运重新绘制中自定义标题和y标签 2022-01-01
- 使用PyInstaller后在Windows中打开可执行文件时出错 2022-01-01