用递归函数替换一个简单的for循环?

时间:2018-04-24 20:17:25

标签: python functional-programming

我正在观看Eric Meijer关于函数式编程的讲座,我发现这个例子真的很棒且很有趣:

如果我必须以命令式方式汇总数字列表,我会做类似的事情:

total=0
for each in range(0, 10):
    total = total + each

我正在解释如何执行此操作,而不是仅指定我想要的内容。

Python中的这个表达式做了同样的事情:

sum(range(1,10))

并且它与我原来的问题陈述相同,即#34;汇总数字列表"。这是一个很好的高级编程语言结构,因此具有可读性和声明性

  1. range(1,10)捕获了这是一个项目列表的事实。
  2. sum捕获要完成的计算。
  3. 所以,我的第一个想法是函数,返回值比for-loops更有用,至少在某些情况下。在进一步阅读时,我还发现for-loops只是执行jump操作的语法糖,也可以用具有适当基本条件的递归函数调用替换。 这是正确的陈述吗?

    因此,我只是编写了一个简单的reduce函数,它看起来像:

    def reduce(operation, start, array):
        # I think I could make this an expression too.
        if len(array) == 1:
            return operation(start, array[0])
        return reduce(operation, operation(start, array[0]), array[1:])
    

    我只是想知道这是否是一种开始在功能上思考的好方法,即尽可能在输入和输出方面?

    我能想到的优点是:

    1. 我们可以创建任意数量的部分,例如sum,product等。但我认为它也可以使用循环来实现。
    2. 缺点是:

      1. 我一次又一次地复制这个数组。空间复杂度为O(n ^ 2)。我可以使用索引来避免这个问题,但代码看起来会很混乱。
      2. 由于Python中没有尾递归,因此可能会创建一个巨大的堆栈。但这是一个需要注意的实现细节。

2 个答案:

答案 0 :(得分:1)

回复:缺点#2

是的,确实会创建一个巨大的堆栈。我在Windows上专门用IronPython体验过这个。如果你在递归次数中得到一个错误(不太可能是一个简单的求和,但在处理外部API时会发生这种情况),你将得到一个堆栈跟踪,并在原始调用后的每一帧中抛出一个错误。这可能使调试变得非常困难。

此代码:

class ConnectedItem():
    def __init__(self, name):
        self.name = name
        self.connected_to = None

    def connect(self, item):
        self.connected_to = item

    def __repr__(self):
        return "<item: {} connected to {}>".format(self.name, self.connected_to)

items = []
for l in ["a", "b", "c", "d"]:
    items += [ConnectedItem(l)]

for n, i in enumerate(items):
    if n < 3:
        i.connect(items[n + 1])

def recursively_access(item):
    # print(item.name)
    return recursively_access(item.connected_to)

recursively_access(items[0])

产生这个:

v0.21.0

答案 1 :(得分:0)

这可能不完全是python,但递归是一种可以在任何语言中使用的方法。这是一个可以帮助您思考正确轨道的示例。

recursiveMethod(param1, param2)
    if (param1 > 10)
        return from method
    recursiveMethod(param1++, param2 += whateverOperation)