【问题标题】:Change a recursion function for a loop更改循环的递归函数
【发布时间】:2014-08-26 04:06:25
【问题描述】:

我读过,python 中的递归工作非常缓慢。是否可以将此递归更改为循环函数,这样可以更快地工作? 我的功能有点复杂,但我会尽量展示最重要的部分:

class Element(object):
    def __init__(self, name):
        self.name = name
        self.priority = randint(1000)
    # some other operations and functions

import heapq

def fun(name):

      if condition():
         e = Element(name)
         # make some operations
         for i in e.sublist:
             if condition2():
                   heapq.heappush(heap,e)
             else:
                   updatepriority(e)
      if heap:
         top = heapq.heappop(heap)
         fun(top.name)

所以我有一个递归函数,它搜索抛出许多子列表并使用 heapq 模块构建一个优先级队列。 如果我有一个递归函数,例如计算斐波那契数,我可以轻松地将递归转换为循环。但是在我的函数中,我没有返回语句,所以我不确定我该怎么做。

【问题讨论】:

  • heap 在用于if heap: 之前未定义。
  • new Element(name) 也不是你在 python 中初始化类的方式。只需使用Element(name)
  • “python 中的递归工作非常缓慢” 据我所知,在 Python 中使用递归并没有天生的慢。与内联循环相比,这是一个额外的函数调用(是否递归),它会减慢速度。还是我错了?
  • Python 没有尾调用优化,因此堆栈会增长,因此您可以获得堆栈溢出或内存不足。堆栈操作将导致它比循环慢一点
  • @AndrewJohnson 是的,因为它是在其他函数中定义的,这里没有,所以我没有写。但我想每个人都知道heap 只是一个列表。

标签: python loops python-2.7 optimization recursion


【解决方案1】:

实际上,我认为您可以相当直接地做到这一点。只需先用你的 root 初始化堆,然后你就可以使用 while 进行迭代。

def fun(root):
  # Initialize the heap with your root element.
  heap = []
  if condition():
    e = Element(root)
    # make some operations
    for i in e.sublist:
      if condition2():
        heapq.heappush(heap,e)
      else:
        updatepriority(e)

  # Now we can iterate through the remainder of the heap.
  while heap:
    top = heapq.heappop(heap)
    if condition():
      e = Element(top.name)
      # make some operations
      for i in e.sublist:
        if condition2():
          heapq.heappush(heap,e)
        else:
          updatepriority(e)

如果您将实际堆元素传递给函数参数,而不是 name,那么您可以立即将其推送到 heap 并跳过初始步骤,从而使您的代码更简单。

def fun(root):
  heap = [root]

  # Now we can iterate through the remainder of the heap.
  while heap:
    top = heapq.heappop(heap)
    if condition():
      e = Element(top.name)
      # make some operations
      for i in e.sublist:
        if condition2():
          heapq.heappush(heap,e)
        else:
          updatepriority(e)

【讨论】:

  • [] is not [] == True
  • 只需使用while heap
  • @kroolik 我知道这是在最初的问题中,但我不知道为什么我不坚持下去。
【解决方案2】:

是的,您总是可以将递归转换为迭代:

  • 首先确保所有递归调用都是尾调用,就像你所做的那样。

    def fun(name):
    
      if condition():
         e = new Element(name)
         # make some operations
         for i in e.sublist:
             if condition2():
                   heapq.heappush(heap,e)
             else:
                   updatepriority(e)
      if heap:
         top = heapq.heappop(heap)
         fun(top.name)
    
  • 然后让尾调用有自己的条件,if heap: 会在代码中出现两次。

    def fun(name):
    
      if condition():
         e = new Element(name)
         # make some operations
         for i in e.sublist:
             if condition2():
                   heapq.heappush(heap,e)
             else:
                   updatepriority(e)
      if heap:
         top = heapq.heappop(heap)
      if heap:
         fun(top.name)
    
  • 现在包裹do … while,移除尾调用并将条件谓词放在while中,并处理递归的参数。

    def fun(name):
      do #not python
    
         if condition():
             e = new Element(name)
             # make some operations
             for i in e.sublist:
                 if condition2():
                     heapq.heappush(heap,e)
                 else:
                     updatepriority(e)
          if heap:
             top = heapq.heappop(heap)
    
          name = top.name
      while heap # not python
    
  • 现在转换为while(python没有do...while)

    def fun(name):
        heap=True
        while heap:
    
            if condition():
                e = new Element(name)
                # make some operations
                for i in e.sublist:
                    if condition2():
                        heapq.heappush(heap,e)
                    else:
                        updatepriority(e)
            if heap:
                top = heapq.heappop(heap)
    
            name = top.name
    

注意:top 的创建不需要是有条件的。 注意:我没有修复你的任何错误

【讨论】:

  • 如果您使用 heapq.heappush(heap,e) 并且已经将 heap 分配为布尔值会怎样?
  • 类似于在定义之前使用它时会发生什么。见注释(我没有修复原始错误)。
猜你喜欢
  • 2010-12-19
  • 2023-03-24
  • 1970-01-01
  • 1970-01-01
  • 2011-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多