• python之路第五篇之递归(进阶篇:续:经典例子剖析)


    递归

    在函数内部,可以调用其他函数;
    如果一个函数在内部调用自身本身,这个函数就是递归函数。

    例如,我们来计算阶乘:

    n! = 1 x 2 x 3 x ... x n,
    

    用函数f1(n)表示,可以看出:

    f1(n) = n! = 1 x 2 x 3 x ... x (n-1) x n 
          = (n-1)! x n = f1(n-1) x n
    

    所以,f1(n)可以表示为 n x f1(n-1),只有n=1时需要特殊处理。
    于是,f1(n)用递归的方式写出来就是:

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

    上面就是一个递归函数。执行结果如下:

    >>> f1(1)
    1
    >>> f1(3)
    6
    >>> f1(10)
    3628800
    

    那么,利用函数编写如下数列:

    斐波那契数列指的是这样一个数列 
    0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,
    610,987,1597,2584,4181,6765,10946,17711,28657,46368 ...
    

    实现代码如下:

    def func(arg1,arg2):
        if arg1 == 0:
            print arg1, arg2
        arg3 = arg1 + arg2
        print arg3
        func(arg2, arg3)
    
    func(0,1)
    

    执行结果如下:(“....”代表省略)

    .....
    26863810024485359386146727202142923967616609318986952340123175997617981700247881689338369654483356564191827856161443356312976673642210350324634850410377680367334151172899169723197082763985615764450078474174626
    	Traceback (most recent call last):
    .....
    334151172899169723197082763985615764450078474174626
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>  #有报错
    ......
    

    为什么上面有报错,难道是程序错了?其实不是,程序没错,因为“斐波那契数” 规律是前两个数相加
    等于后面一个数,而程序一直不断这样执行下去,最终达到系统默认临界值,当然程序也就出错了

    接下来,我们把程序再改改,我们让“不断循环的第三个值”(即arg3)大于1000的时候 返回一个值,
    看看这个时候的效果,直接看下面代码:

    def func1(arg1,arg2):
        if arg1 == 0:
            #print arg1,arg2
            pass
        arg3 = arg1 + arg2
        if arg3 > 1000:
            return arg3
        func1(arg2,arg3)
    
    result = func1(0,1)
    print result
    

    你们觉得上面打印的结果是什么?

    看下面执行结果:

    >>> print result
    None
    

    这是为什么,苦苦熬了这么多年,终于等到你,>~< ...(哈哈,开个玩笑)

    上面代码分解如下:

    def func1(arg1,arg2):   
    #arg1 = 0 ,arg2 = 1,第2次:arg1 = 1,arg2 = 1,第3次:arg1 = 1,arg2 = 2,
    第4次:arg1 = 2,arg2 = 3,
        
        if arg1 == 0:       #满足条件,开始执行 
            #print arg1,arg2
            pass            #不做任何处理
        
        arg3 = arg1 + arg2  #走到这一步,arg3 = 0 + 1 = 1,第2次:arg3 = 1 + 1 = 2,
        第3次,arg3 = 1 + 2 = 3,第4次:arg3 = 2 + 3 = 5, .... 执行到第18次....
        
        if arg3 > 1000:     #第一次循环不符合条件,绕开return arg3,而继续往下执行;....
        假设执行到第18次时符合条件,那么就会执行下面的代码,即 return arg3 会被执行!!!
            
            return arg3     
          #第一次循环不执行,2,3,4次都一样不执行;.....,假设第18次时符合条件,并且执行
          了return arg3,重点来了!!!!,这个时候我们都知道,函数体中,一个值被return,
          那么这个函数的生命周期也就结束,不再往下执行,也就意味着下面的func1(arg2,arg3)
          没有被执行. 	    
        
        func1(arg2,arg3)    
        #自身调用第2个和第3个的值,即第1次为:1 ,1  第2次为1,2,第3次:2,3 第4次:3,5 ....
        假设执行到第18次,这个时候没有被执行,因为上面return的出现,函数生命周期已经结束
        (重点!!:分析:既然18次时符合条件,并且return arg3,函数直接出去了,大家不妨想想,
        那么在出去之前,它的上一次执行,也就是第17次并没有在func1(arg2,arg3)这一步,将这个
        函数的值return(返回)给func1(arg1,arg2),也就意味着,17次没有返回,而18次时,
        函数生命周期也已经结束!之后执行函数外面的操作,result = func1(arg1,arg2),print result,
        接着往下看:
            
    大家都知道,如果要将一个函数赋值给一个变量,假设这么赋值:result = func1(“值”,“值”),
    那么这个函数肯定会有一个返回值,同时赋值给这个变量,由于17次没有return func1(arg2,
    arg3)给func1(arg1,arg2),18次时函数结束,那么这个函数的默认返回值就是None(即空值)
    那么赋值给这个变量和打印这个变量也就是None
    
    同时大家记住一句话:python 函数默认是从上往下执行
    
    	
    result = func1(0,1)  #第一次开始执行,赋值!第18次赋值,这个时候是None
    print result         #第1,2,3,4都不执行,因为这个是在函数外,只有函数结束后才行,....
    第18次,这里打印了最终值"None"
    

    大家是否已经知道

    上面的代码改成下面这样:

    def func1(arg1,arg2):
        if arg1 == 0:
        #print arg1,arg2
            pass
        arg3 = arg1 + arg2
        if arg3 > 1000:
            return arg3
        return func1(arg2,arg3)   #这里return ,所有有值
    

    执行结果如下:

    >>> result = func1(0,1)
    >>> print result
    1597
    

    return 返回值(经典例子):

    你们认为下面的result 结果是什么? 10000???NO,NO,NO

    def n4():
    	return "10000"
    def n3():
    	n4()
    def n2():
    	n3()
    def n1():
    	n2()
    
    result = n1()
    print result
    

    返回值为None

    为什么?

    请听分解:当我们最终print result 时,result = n1(), n1函数调用n2, n2函数调用n3,
    n3函数调用n4,而当n3调用n4时,(n4函数有返回值),并没有return n4(),意味着n3是None,
    因此n2函数在调用n3时,由于n3是None,,同时n3本身也没有return给n2,(就算return给n2了,
    也是None,哈哈)所以最终返回就是None
    

    这个例子是不是很经典?好了,今天很晚了,就分享到这里,因为白天上班,没什么时间写,也就只能晚上
    写了(ps,现在是凌晨2点18分),下次继续新的内容!

    作者:杨英华
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    简单的BMCP位图图片压缩算法
    163相册验证码图片的识别手记之二 识别
    认父亲的DbParameter!!
    文件同步精灵(初版)
    163相册验证码图片的识别手记之一 去除干扰
    C#中WebService里的回车符"\r"丢失问题
    PHP 杂谈《重构改善既有代码的设计》之二 对象之间搬移特性
    PHP5计划任务离线功能的原理
    (转)程序员疫苗:代码注入
    window7环境,不安装Oracle,使用PL/SQL Developer结合oracle精简客户端,管理Oracle数据库
  • 原文地址:https://www.cnblogs.com/yangyinghua/p/4990416.html
Copyright © 2020-2023  润新知