当前位置:   article > 正文

python 学习汇总36:递归函数(尾递归)( tcy)_return n * factorial(n-1) if n else 1

return n * factorial(n-1) if n else 1
递归函数(尾递归)                                                           2018/11/15 
  1. 用途:
  2. 递归函数常用于检索大量数据,替代for循环。

1.递归深度设置:

  1. sys.getrecursionlimit() #返回当前最多的递归深度默认3000 #ipython
  2. sys.setrecursionlimit(1000) #设置递归深度 
  1. 注意:
  2. 不能用在生成器函数和协程中
  3. 函数式编程并未通过 while 或者 for 声明提供迭代功能,同样也未提供状态更新。
  4. 任何可迭代的代码都可以转换为可递归的代码 
2.实例1:定义阶乘函数factorial ;递归实现
  1. def factorial(n):
  2. if n<=1:
  3. return 1
  4. else:
  5. return n * factorial(n-1)

 

实例2:定义阶乘factorial lambda表达式;递归实现
factorial1=(lambda n: 1 if n <= 1 else n * factorial1(n-1))#运行时间稍快于上面
测试 :
  1. sys.setrecursionlimit(3000)#若设定3000,下面n<=2999
  2. a=factorial(1) #1
  3. print(a)
  4. a=factorial(5) #120
  5. print(a)
  6. a=factorial(6) #720
  7. print(a)
实例3:定义斐波那契数;递归实现
  1. def fibonacci(n):
  2. if n==1 or n==2:
  3. return 1
  4. return fibonacci(n-1)+fibonacci(n-2)

 

实例4:定义斐波那契数;lambda递归实现
  1. fibonacci = (lambda x , x1=1,x2=0:
  2. x2 if x == 0 else fibonacci (x - 1, x1 + x2, x1))

 

测试 :
  1. a=fibonacci(1) #1
  2. print(a)
  3. a=fibonacci(5) #5
  4. print(a)
  5. a=fibonacci(6) #8
  6. print(a)

 

3.尾递归
  1. 尾递归基于函数的尾调用, 每一级调用直接返回函数的返回值更新调用栈,而不用创建新的调用栈,
  2. 类似迭代的实现,时间和空间上均优化了一般递归! 
  1. python不支持尾递归。解决办法先定义一个修饰符,然后在定义尾递归函数。
  2. 参考:
  3. http://www.open-open.com/lib/view/open1480494663229.html 

尾递归定义实例:

  1. 阶乘实例函数修改为支持尾递归,不需要在设置递归深度
  2. 如果无修饰符那么n的能用数据范围为2899(假设你设定递归深度为3000的话)
  1. @tail_call_optimized #修饰符函数在下面定义
  2. def factorial(n,acc=1):#阶乘
  3. if n==0:
  4. return acc
  5. else:
  6. return n*factorial(n-1,n*acc) 

测试:

  1. def factorial(n):#普通阶乘递归定义,用于测试比对
  2. if n<=1:
  3. return 1
  4. else:
  5. return n * factorial(n-1)
  1. n=2999
  2. for i in range(n):
  3. if factorial(i)==factorial1(i):
  4. # print('ok')
  5. pass
  6. else:
  7. print('ng')
  8. print('end') 
4.备注:
@tail_call_optimized的定义 :
4.1.异常类定义
  1. class TailRecurseException(Exception):
  2. def __init__(self, args, kwargs):
  3. self.args = args
  4. self.kwargs = kwargs

 

4.2.尾递归修饰符函数 :

  1. def tail_call_optimized(g):
  2. """
  3. 这个函数用尾调用优化来修饰函数。它通过抛出一个异常(如果是它自己的祖父母)来实现这一点,
  4. 并捕获这样的异常来伪造尾调用优化。如果修饰函数在非尾上下文中递归,则此函数将失败。
  5. """
  6. def func(*args, **kwargs):
  7. ''''
  8. 函数默认第一层递归是父调用,对于尾递归, 不希望产生新的函数调用(即:祖父调用),
  9. 所以这里抛出异常, 拿到参数, 退出被修饰函数的递归调用栈
  10. '''
  11. f = sys._getframe()
  12. if f.f_back and f.f_back.f_back and f.f_back.f_back.f_code == f.f_code:
  13. raise TailRecurseException(args, kwargs)# 抛出异常
  14. else:
  15. while 1:
  16. try:
  17. return g(*args, **kwargs)
  18. except TailRecurseException as e:
  19. args = e.args # 捕获异常, 拿到参数, 退出被修饰函数的递归调用栈
  20. kwargs = e.kwargs
  21. func.__doc__ = g.__doc__
  22. return func

 

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

闽ICP备14008679号