for 循环和列表推导不等价。
想象一下我们有:
>>> def sort(a, _): return 2*a
...
>>> i=0
然后:
>>> ans=list(range(5))
>>> ans = [sort(a, i + 1) for a in ans]
>>> ans
[0, 2, 4, 6, 8]
但是:
>>> ans=list(range(5))
>>> for a in ans: ans=(sort(a, i+1))
>>> ans
8
列表理解基本上是:
- 将
sort(a, i+1) 应用于ans 中的每个a
- 然后将结果分配给变量
ans 本身。
正如@chepner 在评论中所说,这里没有递归[1]。相当于:
>>> ans=list(range(5))
>>> new_ans = [sort(a, i + 1) for a in ans]
>>> ans = new_ans
>>> new_ans
[0, 2, 4, 6, 8]
而 for 循环:
- 迭代
ans:
- 为每个
a 分配sort(a, i+1) 到ans
因此,分配给出:ans = sort(ans[0], i+1),然后是ans = sort(ans[1], i+1),...,ans = sort(ans[-1], i+1),其中ans[-1] 是原始ans 的最后一个元素2。 p>
列表理解的循环等效项是:
>>> ans=list(range(5))
>>> new_ans=[]
>>> for a in ans: new_ans.append(sort(a, i+1))
>>> ans = new_ans # assignement here
>>> ans
[0, 2, 4, 6, 8]
[1] 一个函数可能使用递归,但我不确定递归对于列表理解意味着什么,除非你使用一些肮脏的技巧:记录https://stackoverflow.com/a/221874/6914441。
[2]注意变量ans的重新赋值不会修改原列表:
- 当循环开始时,Python 在列表上创建一个迭代器并在列表中保留一个引用;
- 当
ans 被重新影响时,for 循环仍然具有原始列表中的引用。
如果您从循环体中修改列表,情况会有所不同(强烈建议):
>>> xs=list(range(5))
>>> for x in xs: print(x, xs);_=xs.pop(0)
...
0 [0, 1, 2, 3, 4]
2 [1, 2, 3, 4]
4 [2, 3, 4]
我们每次迭代都会删除第一个元素,但索引会继续增长:
[*0*, 1, 2, 3, 4] # then pop 0
[1, *2*, 3, 4] # then pop 1
[2, 3, *4*] # then pop 2