《笨办法学Python》(22)---函数概念:循环VS递归,尾递归

参考文档

http://www.cnblogs.com/liunnis/articles/4604967.html

https://blog.csdn.net/tianpingxian/article/details/80821504

https://blog.csdn.net/tcy23456/article/details/84111639   #py不支持尾递归

 

尾调用是在函数的尾部,调用另一个函数,因为函数是语言没有循环,递归很重要,对于递归需要来不断优化,一般采用尾调用或尾递归来优化。

顾名思义,尾递归就是从最后开始计算, 每递归一次就算出相应的结果, 也就是说, 函数调用出现在调用者函数的尾部 ,尾递归就是把当前的运算结果(或路径)放在参数里传给下层函数和普通递归区别在于内存占用。

 

循环与递归(阶乘的例子)

 

循环 cycle  cyclic

打印中间过程的循环

>>> def funcA2(n):
    fact=1
    for i in range(n):
        fact=fact*(i+1)
        print(i+1,"'s fact is",fact) #这个可以不要
    return fact

>>> funcA2(5)
1 's fact is 1
2 's fact is 2
3 's fact is 6
4 's fact is 24
5 's fact is 120
120
>>> 

简写循环

>>> def funcCycle(n):
    fact=1
    for i in range(1,n+1,1):
        fact*=i
    return fact

>>> funcCycle(5)
120

 

递归 recursion

什么叫递归?如果一个函数在内部调用自己,就被称为递归

(1)递归理论上全部都可以写成递归?

(2)递归写起来看起来比循环要简单,逻辑更清晰

>>> def funcA1(n):
    if n ==1:
        return 1
    return n*funcA1(n-1)

>>> funcA1(5)
120

定义阶乘factorial lambda表达式;递归实现

 

>>> funcAA1=(lambda n:1 if n==1 else n*funcAA1(n-1))
>>> funcAA1(5)
120

 

 

递归的问题:

(1) 这种递归,是反复调用自己,直到条件满足(和while相反逻辑)

(2)但是因为反复调用,会导致在最后1次计算,计算压力大

(3)使用递归函数需要注意防止栈溢出。

函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。

(4)不能用在生成器函数和协程中??

>>> import sys
>>> sys.getrecursionlimit()
1000

可以试试fact(1000):会报错  maximum recursion depth exceeded

 

​stack的堆积

5*4*3*2*funcA1(1)

5*4*3*funcA1(2)

5*4*funcA1(3)

5×funcA1(4)

 

 

 

 

尾递归 tail_recursion

尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。

(1)解决递归调用栈溢出的方法是通过尾递归优化

         事实上尾递归和循环的效果是一样的,把循环看成是一种特殊的尾递归函数也是可以的。

(2) 每次递归都计算了一次,没放到最后计算,压力也小

(3)尾递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。

>>> def funcRecursion1(n,product=1):
    if n==1:
        return product
    return funcRecursion1(n-1,n*product)

>>> funcRecursion1(5,1)
120
>>> funcRecursion1(3,1)
6
>>> 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值