递归和绑定

时间:2017-05-11 01:29:51

标签: python recursion

我正在尝试理解如何使用递归,我遇到了一些麻烦。

所以从我的理解,如果你试图使用局部变量,该值将重置,因为每次递归都从函数顶部开始(如a = []每次都会重置为空列表)。

有没有办法在保持值的同时完成递归(例如,如果我将值添加到列表中)并将其保持在本地级别(在函数内)?

2 个答案:

答案 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]