递归比迭代更差吗?

时间:2016-04-01 09:23:53

标签: python python-2.7 loops recursion

前几天有人对我说,递归会比迭代更好,如果可能的话,应该总是使用。

所以,我进入递归并尝试编写一个简单的程序来获得数字的阶乘。这是递归:

def fact(n):
    if n == 1:
        return 1
    return n * fact(n - 1)

虽然这种方法很好,但只要RuntimeError: maximum recursion depth exceeded达到997以上就会得到n

所以我编写了一个完全相同的简单函数,但使用for loop

def fact(n):
    a = 1
    for x in range (0, n, 1):
        a = a * (n - x)
    return a

虽然n < 10000在150毫秒内给出答案。

所以,我可能会因为数字较少而递归速度更快,但是没有。这需要更长时间: timing of recursion and iteration

所以我的问题是:
 在用Python编写程序时是否有任何理由使用递归?
和:
是否有任何问题只能通过递归来解决?

3 个答案:

答案 0 :(得分:5)

没有问题需要通过显式递归来解决;并且没有任何问题需要通过显式迭代来解决 - Church and Turing have proved它们是可以互换的。

然而,有些问题有更简洁的代码,如果使用递归则更容易推理。实际上,Python标准库甚至C代码本身在许多地方内部使用递归,因此很容易在许多地方遇到可怕的递归限制,例如打印repr嵌套元组:

>>> from functools import reduce
>>> x = reduce(lambda x, y: (x,), range(10000))
>>> x  # recursion limit hit in C code
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: maximum recursion depth exceeded while getting the repr of a tuple
>>> import pprint
>>> pprint.pprint(x)  # recursion limit hit in Python standard library code.
Traceback (most recent call last):
...
  File "/usr/lib/python3.4/pprint.py", line 390, in _safe_repr
    orepr, oreadable, orecur = _safe_repr(o, context, maxlevels, level)
  File "/usr/lib/python3.4/pprint.py", line 340, in _safe_repr
    if issubclass(typ, dict) and r is dict.__repr__:
RuntimeError: maximum recursion depth exceeded while calling a Python object

您总是可以将递归算法转换为具有状态机和中间参数堆栈的迭代,因为毕竟这非常适合CPU实现递归。

答案 1 :(得分:2)

我无法分辨哪个更快,但递归肯定在编程中占有一席之地。例如,考虑以下函数,该函数应该被压平&#34;嵌套列表,成为一个很棒的大清单:

def expand_list(lst):
    result = []
    for element in lst:
        if isinstance(element, list):
            result += expand_list(element)
        else:
            result.append(element)
    return result

(例如expand_list([1,2,3,[4,5,[6,7]]])评估为[1,2,3,4,5,6,7]

迭代无法很好地处理这个问题。

(旁注:Python中的函数与上面的函数一样 - 这只是一个例子。)

答案 2 :(得分:1)

迭代通常(在这种情况下)也更有效(性能明智,假设您正在执行类似的操作)。递归具有更多的开销,因为每次都需要进行新的函数调用,这会花费资源。

https://en.wikipedia.org/wiki/Recursion_(computer_science)

  

&#34;递归的力量显然在于定义的可能性   有限陈述的一组无限的对象&#34;

但是用例必须非常具体,因为递归才是更好的选择。

关于错误,Python有一个内置函数,它返回最大递归深度,如果你觉得这很有用:https://docs.python.org/2/library/sys.html#sys.getrecursionlimit