下面这段代码的输出结果将是什么?请解释。
1 | ls = [1, 2, 3, 4, 5] |
上面代码输出结果将是:
1 | 1 |
画图来分步理解一下:
1 | ls = [1, 2, 3, 4, 5] |
创建对象引用,变量 ls 指向一个列表对象,列表中的每个位置指向了对应的值。

接下来使用 for 循环进行迭代,我们知道 for 循环的本质是先用 iter() 方法将可迭代的对象做成一个迭代器(iterator),然后再对其不断地调用 next() 取出值,最后处理 StopIteration 异常。
现在,我们将每一次迭代拆开看一下。
1 | ls[-2] = ls[0] |
此时,ls[-2] 指向列表中第一个位置所指向的元素,也就是 ls[-2] = 1,此时列表就变成了 ls = [1, 2, 3, 1, 5] 。

1 | ls[-2] = ls[1] |
此时,ls[-2] 指向列表中第二个位置所指向的元素,也就是 ls[-2] = 2,此时列表就变成了 ls = [1, 2, 3, 2, 5] 。

1 | ls[-2] = ls[2] |
此时,ls[-2] 指向列表中第三个位置所指向的元素,也就是 ls[-2] = 3,此时列表就变成了 ls = [1, 2, 3, 3, 5] 。

1 | ls[-2] = ls[3] |
此时,ls[-2] 指向列表中第四个位置所指向的元素,请注意此时列表的第四个位置就是倒数第二个位置,即 ls[3] 等同于 ls[-2],而此时的 ls[-2] 指向的是上一次迭代时所指向的对象,也就是 ls[-2] = ls[-2],进一步地 ls[-2] = 3 而不是 4,此时列表就变成了 ls = [1, 2, 3, 3, 5] 。

1 | ls[-2] = ls[4] |
此时,ls[-2] 指向列表中第五个位置所指向的元素,也就是 ls[-2] = 5,此时列表就变成了 ls = [1, 2, 3, 5, 5] 。

最后我们将每一次迭代过程中的 ls[-2] 所指向的数值汇总,也就是:
1 | 1 |
现在,我们修改代码打印每个元素的内存地址来做进一步的验证:
1 | ls = [1, 2, 3, 4, 5] |
最后得到的执行结果说明我们的推算是正确的:
