下面这段代码的输出结果将是什么?请解释。
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] |
最后得到的执行结果说明我们的推算是正确的: