【问题标题】:Python, Make an iterative function into a recursive functionPython,将迭代函数变成递归函数
【发布时间】:2019-03-01 02:11:39
【问题描述】:

我创建了一个迭代函数,它输出 4 3 2 1 0 1 2 3 4。

def bounce2(n):
    s = n
    for i in range(n):
        print(n)
        n = n-1

    if n <= 0:
        for i in range(s+1):
            print(-n)
            n = n-1
    return
bounce2(4)

如果我想要一个做同样事情的递归函数,我应该怎么想?

【问题讨论】:

  • 与问题无关:请记住,Python 中的分号对于带有单个语句的行是可选的,一般建议将其省略。
  • 你不应该想要一个递归函数来代替一个迭代函数; Python 不能有效地处理递归。
  • @chepner 除非这是一个学习递归的练习。
  • 由于递归实际上只在 Python 中用于遍历递归数据结构,我怀疑这些类型的转换是否有用。

标签: python loops recursion


【解决方案1】:

试试这个:

def bounce(n):
    if n >= 0:
        print(n)
        bounce(n - 1)

        if n:
            print(n)

bounce(4)

输出将是: 4 3 2 1 0 1 2 3 4

【讨论】:

    【解决方案2】:

    @mehrdad-pedramfar 发布了一个很好的答案。你也可以试试这个更精致的:

    def my_recursion(current_value, first_portion):
        if current_value == 5:
            return
        print(current_value)
        if current_value == 0 or not first_portion:
            my_recursion(current_value + 1, False)
    
        elif first_portion:
            my_recursion(current_value - 1, True)
    
    
    my_recursion(4, True)
    

    【讨论】:

      【解决方案3】:

      与第一个基本相同。输出不同 - 你会得到双 0。 只是为了表明您可以在递归调用之前和之后进行打印。

      def bounce(n):
      
          if n >= 0:
              print(n)
              bounce(n - 1)
              print(n)
      

      3 2 1 0 0 1 2 3

      【讨论】:

        【解决方案4】:

        预期输出:

        4 3 2 1 0 1 2 3 4
        

        让我把它放在一个图表中:

        4
          3
            2
              1
                0
              1
            2
          3
        4
        

        让我们把它放到代码中:

        def bounce(n):
            print(n)
            if n:
                bounce(n - 1)
                print(n)
        

        或者我可以将其视为树遍历 - 向下和向上(嗯,在这种情况下,树是相当线性的):

        ↓
          4
        ↓ | ↑
          3
        ↓ | ↑
          2
        ↓ | ↑
          1
        ↓ | ↑
          0
        

        有多种方法可以创建tree traversal,我会在这里选择 DFS - depth-first search

        DFS 伪代码:

        procedure DFS(G,v):
            label v as discovered
            for all edges from v to w in G.adjacentEdges(v) do
                if vertex w is not labeled as discovered then
                    recursively call DFS(G,w)
        

        实际上它是为图表而设计的,而不仅仅是树;对于树,我们不必执行“已发现标签”部分。

        将此 DFS 转换为 Python:

        def dfs(node):
            for child_node in node:
                dfs(child_node)
        

        4 3 2 1 0 的情况下,我们不需要for,因为只有一个或零个子节点 - n - 1 只要n &gt; 0

        def our_dfs(n):
            if n > 0:
                child_node = n - 1
                our_dfs(child_node)
        

        但这只是遍历,还没有真正有用的东西。让我们注入我们的“业务逻辑”:

        def bounce(n):
            # stuff that happens before we go down
            print(n)
            # descend
            if n > 0:
                child_node = n - 1
                bounce(child_node)
            # stuff that happens after we are back from processing the subtree
            if n > 0:
                print(n)
        

        因为我们相信良好的工艺并且我们想要生成干净的代码(好吧,我现在开始开玩笑了)我们想要只做一件事的函数 - 一个用于 DFS 的函数,一个代表我们的树的函数,一个单独的函数( s) 对于我们的业务逻辑:

        def dfs(node, child_factory, before_stuff, after_stuff):
            before_stuff(node)
            for child_node in get_child_nodes(node):
                dfs(child_node, child_factory, before_stuff, after_stuff)
            after_stuff(node)
        
        def get_child_nodes(n):
            if n:
                yield n - 1
        
        def print_before(node):
            print(node)
        
        def print_after(node):
            if node:
                print(node)
        
        def bounce(n):
            dfs(n, get_child_nodes, print_before, print_after)
        
        bounce(4)
        

        也许我们可以通过使用嵌套函数使dfs 函数更简单一些:

        def dfs(node, child_factory, before_stuff, after_stuff):
            def f(node):
                before_stuff(node)
                for child_node in get_child_nodes(node):
                    f(child_node)
                after_stuff(node)
            f(node)
        

        嘿,看一下,我还有一个想法……我们可以将其修改为一个函数,该函数返回一个可以执行 DFS 的函数 (closure):

        def make_dfs(child_factory, before_stuff, after_stuff):
            def dfs(node):
                before_stuff(node)
                for child_node in get_child_nodes(node):
                    dfs(child_node)
                after_stuff(node)
            return dfs
        

        所以弹跳程序现在变成:

        def get_child_nodes(n):
            if n:
                yield n - 1
        
        def print_before(node):
            print(node)
        
        def print_after(node):
            if node:
                print(node)
        
        def make_dfs(child_factory, before_stuff, after_stuff):
            def dfs(node):
                before_stuff(node)
                for child_node in get_child_nodes(node):
                    dfs(child_node)
                after_stuff(node)
            return dfs
        
        bounce = make_dfs(get_child_nodes, print_before, print_after)
        
        bounce(4)
        

        那么,这个解决方案有什么了不起的呢? (注意:仍然在开玩笑,部分)你知道,Python 有一个recursion limit。可以嵌套多少个函数调用是有限的,而且这个数字非常低。这是使用递归函数处理未知输入的一大缺点(有时甚至是安全问题)。所以现在怎么办?好吧,只需将 make_dfs 的实现替换为基于堆栈的东西(参见 DFS 维基百科页面)而不是递归。完毕。您无需触摸其他任何东西。

        【讨论】:

          猜你喜欢
          • 2011-11-30
          • 2012-10-17
          • 1970-01-01
          • 2021-12-31
          • 2012-07-12
          • 2020-08-08
          • 2015-05-30
          相关资源
          最近更新 更多