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

版权声明:一起学习,一起成长,欢迎关注犀牛先生的博客 https://blog.csdn.net/xuemanqianshan/article/details/85111642

参考文档

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
>>> 

 

猜你喜欢

转载自blog.csdn.net/xuemanqianshan/article/details/85111642