我正在尝试理解如何使用递归,我遇到了一些麻烦。
所以从我的理解,如果你试图使用局部变量,该值将重置,因为每次递归都从函数顶部开始(如a = []每次都会重置为空列表)。
有没有办法在保持值的同时完成递归(例如,如果我将值添加到列表中)并将其保持在本地级别(在函数内)?
答案 0 :(得分:0)
我用两种不同的方法来处理这个问题。每个示例都将生成列表[1, 2, 3, 4]
。
第一种方法使用的默认参数最初为空,但稍后用于将累加器传递给更深的调用。
def build_range(n, accumulator=None):
accumulator = accumulator or []
if n == 0:
return accumulator
accumulator.insert(0, n)
return build_range(n-1, accumulator)
print build_range(4) # [1, 2, 3, 4]
第二种方法使用列表串联通过对较小的列表求和来构建列表。请注意,这种方法对于列表并不是很好,因为您不得不构建新的列表,但对于不可变数据类型可以更清晰。
def build_range(n):
if n == 0:
return []
return build_range(n-1) + [n]
print build_range(4) # [1, 2, 3, 4]
然后,第三种非递归方法是展开递归循环。
def build_range(n):
accumulator = []
while n:
accumulator.insert(0, n)
n -= 1
return accumulator
print build_range(4) # [1, 2, 3, 4]
显然,这是一种折磨,低效的向后构建范围的例子(插入不如追加更理想),但希望它可以解决这些问题。
答案 1 :(得分:0)
这是一个很难回答的问题,因为你不清楚你理解什么,不理解什么。 @JaredGoguen尝试向您展示各种技巧。我想给它添加几个
此实现使用辅助递归函数。它与Jared的第二个实现类似,但由于它的尾调用,它可以放在蹦床上以使其堆栈安全。这是我至少90%的时间实现递归过程的方法。
def build_range (n):
def aux (m, acc):
if m == n:
return acc
else:
return aux(m + 1, acc + [m])
return aux(0, [])
print(build_range(4))
# [0, 1, 2, 3]
此技术的另一个变体是使用lambda作为累加器。这对于在正向方向上构建可迭代特别有用,而不必将待处理结果保留在堆栈上。再次,由于尾部调用,可以进行一个微不足道的修改来利用蹦床并使其安全堆栈
def map (f, xs):
def aux(xs, k):
if not xs:
return k([])
else:
return aux(xs[1:], lambda ys: k([f(xs[0])] + ys))
return aux(xs, lambda x: x)
print(map(lambda x: x * x, [1,2,3,4]))
# [1, 4, 9, 16]