【问题标题】:Understanding list comprehension that uses recursion理解使用递归的列表理解
【发布时间】:2019-03-21 04:11:16
【问题描述】:

我目前正在学习列表理解,遇到了这行递归代码:

ans = [sort(a, i + 1) for a in ans]

我尝试用以下内容替换该行:

for a in ans:
    ans = (sort(a, i + 1))

有人可以帮我理解我在哪里犯了错误吗?

谢谢!

【问题讨论】:

  • 不是递归的;它只是创建一个新列表,然后将其分配给相同的名称。
  • 啊,我明白了!谢谢

标签: recursion list-comprehension


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 2015-03-10
    • 2020-10-17
    • 2013-02-09
    • 2016-02-06
    • 2011-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多