python - 有什么方法可以使递归函数更快吗?

标签 python recursion

经过对递归函数的一些研究后,我面临着矛盾:一方面以递归方式解决问题很优雅,但另一方面在实践中性能似乎很糟糕并且递归调用的数量是有限的。

我知道默认情况下 Python 的递归深度限制为 1000,但是即使在一个简单的应用程序中,早在 40 - 50 次调用时我的性能就非常糟糕。

举个例子:

def fibonacci(n):
    if n == 1 or n == 0:
        return 1
    else:
        return fibonacci(n-1) + fibonacci(n-2)

我的电脑上的这个简单的递归函数即使对于低 n 也需要大量的时间来求解。为了测试我还编写了另一个函数:

def fib_nonrecursive(n):
    fib_seq = [1, 1]
    for i in range(2, n+1):
        value = fib_seq[i-1] + fib_seq[i-2]
        fib_seq.append(value)        
    return fib_seq[i]

即使对于大数,非递归方法也非常快,因此问题绝对不是涉及的运算或数字的大小。所以我的问题是为什么递归方式这么慢,有什么方法可以让它更快吗?有没有办法扩大递归深度?

编辑 由于答案建议使用记忆化,我研究了它并在我的示例中实现了它:

def mem(f):
    memory = {}
    def inner_function(x):
        if x not in memory:            
            memory[x] = f(x)
            return memory[x]
        else:
            return memory[x]
    return inner_function

@mem
def fibonacci(n):
    if n == 1 or n == 0:
        return 1
    else:
        return fibonacci(n-1) + fibonacci(n-2)

相同的mem(f)可以与其他递归函数f一起使用。必须包含 @mem 部分,才能将 f 作为参数传递给 mem()(请参阅“装饰器”) 这是稍微先进的编码方式,但我没有找到更简单的方法来为给定的示例实现记忆化。如果有更简单的实现方式请指正。

最佳答案

忽略 fibonacci() 是记忆化的教科书案例(这会使其速度更快)这一事实,“深度且廉价”的递归在普通 Python 中根本不是一个东西。

在许多语言中都存在尾调用消除。 Python没有这个。在许多语言中,推送额外的堆栈帧非常便宜。在 Python 中并非如此。

要找到存在问题的实际代码并不容易,这可能在某种程度上解释了为什么 Python 人员保持简单并始终创建具有完整调试能力的真正堆栈框架。大多数 Python 应用程序中对廉价和深度递归的需求并不多。

关于python - 有什么方法可以使递归函数更快吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44201059/

相关文章:

python - unittest.mock.补丁 : Context manager vs setUp/tearDown in unittest

python - Django : SSLError: [SSL] PEM lib with APNS

python - 在进行 pandas 合并时,用唯一的 "na"标识符填充 "na"值

php - 如何在php中递归地展平树数组?

javascript - 简单的递归函数在嵌套数据中查找父对象却找不到父对象?

python - 在 OpenCV 中处理大型(超过 3000x3000)图像,但它们不适合我的屏幕

python - 范围为 "class"的 Pytest fixture 在每个方法上运行

c - 如何获得使用递归的警告?

javascript - 将对象的递归数组转换为javascript中的嵌套或递归对象

c - 递归 BubbleSort 给出错误的输出