当前位置:   article > 正文

python 尾递归_python尾递归

python尾递归

网上有篇搞笑文 python 程序员进化 http://coolshell.cn/articles/2082.html ,对那个尾递归产生了兴趣。尾递归是指以迭代计算过程执行递归定义的语句,在python等语言中一般都是需要while, do, for这样的特殊语法。而 http://code.activestate.com/recipes/474088/ 有人实现了一个不需要这些语句的python尾递归,巨强无比。

代码我拷过来,便于看一下

  1. ## {{{ http://code.activestate.com/recipes/474088/ (r1)
  2. #!/usr/bin/env python2.4
  3. # This program shows off a python decorator(
  4. # which implements tail call optimization. It
  5. # does this by throwing an exception if it is
  6. # it's own grandparent, and catching such
  7. # exceptions to recall the stack.
  8. import sys
  9. class TailRecurseException:
  10. def __init__(self, args, kwargs):
  11. self.args = args
  12. self.kwargs = kwargs
  13. def tail_call_optimized(g):
  14. """
  15. This function decorates a function with tail call
  16. optimization. It does this by throwing an exception
  17. if it is it's own grandparent, and catching such
  18. exceptions to fake the tail call optimization.
  19. This function fails if the decorated
  20. function recurses in a non-tail context.
  21. """
  22. def func(*args, **kwargs):
  23. f = sys._getframe()
  24. if f.f_back and f.f_back.f_back \
  25. and f.f_back.f_back.f_code == f.f_code:
  26. raise TailRecurseException(args, kwargs)
  27. else:
  28. while 1:
  29. try:
  30. return g(*args, **kwargs)
  31. except TailRecurseException, e:
  32. args = e.args
  33. kwargs = e.kwargs
  34. func.__doc__ = g.__doc__
  35. return func
  36. @tail_call_optimized
  37. def factorial(n, acc=1):
  38. "calculate a factorial"
  39. if n == 0:
  40. return acc
  41. return factorial(n-1, n*acc)
  42. print factorial(10000)
  43. # prints a big, big number,
  44. # but doesn't hit the recursion limit.
  45. @tail_call_optimized
  46. def fib(i, current = 0, next = 1):
  47. if i == 0:
  48. return current
  49. else:
  50. return fib(i - 1, next, current + next)
  51. print fib(10000)
  52. # also prints a big number,
  53. # but doesn't hit the recursion limit.
  54. ## end of http://code.activestate.com/recipes/474088/ }}}

这个尾递归的实现运用了decorator和exception机制, 基本原理是判断是否递归,是递归则抛出异常,然后捕捉异常重新调用。

ps. sys._getframe() 返回当前frame 对象

举例说明一下, factorial(2),由于decortaor,调用顺序是:

  1. --func ------(2, )
  2. ----factorial(2, 1)
  3. ------func----(1, 2)                          
  4. --------raise TailRecurException 
  5.         back to func ---(1,2)
  6.       back to factorial(1,2)
  7.     back ot func ----(2,)
  8.   call factorial(1,2)
  9.   .
  10.   .
  11.   .

基本情况就是这样, 这里也非常取巧,利用参数解析来达到递归的效果

如果像下面定义一个递归函数,就不能使用这个尾递归了

  1. @tail_call_optimized
  2. def fff(n):
  3. if n == 0:
  4. return 1
  5. return n*fff(n-1)
  6. print fff(5)




声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/116140?site
推荐阅读
相关标签
  

闽ICP备14008679号