为什么我的交换列表中两个元素的代码会出错?

zyc*_*hyz 5 python swap python-3.x iterable-unpacking

这是我的代码:

a = [1, 2, 3, 4, 5]
a[0], a[a[0]] = a[a[0]], a[0]
print(a)
Run Code Online (Sandbox Code Playgroud)

我正在尝试交换a[0]a[a[0]]a[1]在本例中),所以我期望的结果是:

[2, 1, 3, 4, 5]
Run Code Online (Sandbox Code Playgroud)

我得到的结果是[2, 2, 1, 4, 5],这不是我想要的。

如果我简化a[0], a[a[0]] = a[a[0]], a[0]a[0], a[1] = a[1], a[0],它就有效。

我怎样才能使列表内的交换像a, b = b, a以前那样工作?

Zer*_*eus 2

这项任务的作用相当大。让我们分解一切 \xe2\x80\xa6

\n\n
a = [1, 2, 3, 4, 5]\n
Run Code Online (Sandbox Code Playgroud)\n\n

好吧,这就是最简单的一点。下一个:

\n\n
a[0], a[a[0]] = a[a[0]], a[0]\n
Run Code Online (Sandbox Code Playgroud)\n\n

任何赋值中发生的第一件事是评估右侧,因此:

\n\n

a[a[0]], a[0]减少到a[1], a[0],其计算结果为(2, 1)

\n\n

然后,每个分配目标依次从分配给它的右侧获取这些项目之一:

\n\n
a[0] = 2   # 2 == first item in the (already evaluated) right hand side\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在已经完成了,a看起来像这样:

\n\n
[2, 2, 3, 4, 5]\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在我们要做第二个作业:

\n\n
a[a[0]] = 1   # 1 == second item in the (already evaluated) right hand side\n
Run Code Online (Sandbox Code Playgroud)\n\n

可是等等!a[0]就是现在2,所以这减少到

\n\n
a[2] = 1\n
Run Code Online (Sandbox Code Playgroud)\n\n

而且,你瞧,如果我们看一下a,结果是:

\n\n
[2, 2, 1, 4, 5]\n
Run Code Online (Sandbox Code Playgroud)\n\n

您发现,尽管 Python 声称能够使用 eg 同时交换两个值a, b = b, a,但事实并非如此。它在实践中几乎总是有效,但如果其中一个值是另一个值的描述的一部分 \xe2\x80\x93 在这种情况下,a[0]是 \xe2\x80\x93 的描述的一部分,a[a[0]]那么实现细节可能会绊倒你向上。

\n\n

解决此问题的方法是a[0]在开始重新分配事物之前存储 的初始值:

\n\n
a = [1, 2, 3, 4, 5]\ntmp = a[0]\na[0], a[tmp] = a[tmp], a[0]\n
Run Code Online (Sandbox Code Playgroud)\n\n

之后,a看起来就像你期望的那样:

\n\n
[2, 1, 3, 4, 5]\n
Run Code Online (Sandbox Code Playgroud)\n