Python 为什么这个递归函数会快速增加内存使用?

Python 为什么这个递归函数会快速增加内存使用?,python,recursion,memory-management,Python,Recursion,Memory Management,我用Python编写了以下递归函数来索引str值的list(同一个值可能在列表中重复多次)。该函数接受一个列表,并返回一个dict,其中字典的每个条目都是项目列表(一个str)和相应的int索引 def make_indices(entries): def _make_indices(ent, idxs, idx): if not ent: return idxs else: _make_indices(en

我用Python编写了以下递归函数来索引
str
值的
list
(同一个值可能在列表中重复多次)。该函数接受一个
列表
,并返回一个
dict
,其中字典的每个条目都是项目列表(一个
str
)和相应的
int
索引

def make_indices(entries):
    def _make_indices(ent, idxs, idx):
        if not ent:
            return idxs
        else:
            _make_indices(ent[1:], idxs, idx) if ent[0] in idxs \
                else _make_indices(ent[1:], dict({ent[0]: idx}, **idxs), idx+1)
    return _make_indices(entries, {}, 0)

我认为这将是一个优雅的解决方案,但它的内存使用会随着列表的长度而迅速增加。是否有人能够解释到底是什么原因导致了内存的过度使用?

切片列表
ent[1://code>,将导致新分配的切片部分的浅拷贝。此外,由于Python没有优化尾部递归,因此您将处于这样一种情况:在外部调用终止之前,所做的每个片都将保持分配状态


尝试调用
ent.pop(0)
删除列表的第一个元素,然后将列表作为
ent
传递而不进行切片。这样,就不需要新的分配了

我的Python很弱,所以这主要是一种猜测-您是否在每个递归步骤中复制列表/字典?如果是这样的话,你就必须等到整个算法停止,才能清除所有的数据,同时你还要保存一个列表的多个副本或至少部分副本。这可能会造成空间复杂性。
O(n!)?这里可能存在二次内存消耗问题,因为在递归结束之前,所有临时内存都不会从堆栈中清除(以及构建所有这些临时内存的二次运行时问题),但是,在这成为一个主要问题之前,您可能会遇到堆栈溢出。另外,您忘记了在
else
分支中返回
return
,因此此函数通常会返回
None
@user2357112supportsMonica这是一个很好的例子!谢谢我确实同意在代码中的某个地方有复制,但我想知道在函数的每次递归调用中复制的是什么,这使得内存使用量增长得如此之快。关于
ent[1://code>的有趣之处。我可以看出这本身是如何导致内存使用量的快速增加的。我意识到Python中缺少尾部递归优化,但没想到这会导致内存使用出现如此大的问题。将尝试使用
ent.pop(0)
建议进行比较。@user1953384尾部递归点总是有一些与之相关的内存开销,因为它需要为每个调用分配堆栈。然而,在每个深度分配新的空间会增加成本。在函数作用域终止之前(除非您显式地
del
或重新分配名称),不能取消分配局部变量的值,并且在没有尾部递归优化的情况下,所有函数作用域将同时保持打开状态,直到最终返回。