喜欢一个人需要理由吗?需要吗?不需要吗?需要吗?不需要吗?这是个鬼知道天晓得的事情。本来你什么也不在乎,开开心心的、吃着火锅、坐着火车、唱着歌出了城......忽然间火车被人掀翻到水里了,你从水里钻了出来,睁眼看见一个细腰长腿一头长发的女土匪,一脚踩在你的脸上,威风凛凛,说此山是我开此树是我栽要想打此过留下买路财,若敢说个不字管杀不管埋!你心里一动,恨不得留下来和她一起当土匪......那个瞬间你就喜欢上她了呗。

递归定义

递归函数:这个函数在他的内部调用了自身。函数自己调用自己,实现递归。

递归特性:

  1. 记住所有的递归函数都有一个退出条件
  2. 相邻两次重复之间有紧密的联系,前一次要为后一次做准备(通常前一次的输出就作为后一次的输入)。
  3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)

普通算法实现高斯求和:

def sum(munber):
    total=0
    for i in range(1,munber+1):
        total+=i
    return total
print sum(100)

运行结果:

5050

如果使用递归方法:

def sum_number(number):
    if number==0:
        return False
    return sum_number(number-1)+number
    # 第一次是sum_number(99)+100的值
    # 第二次是sum_number(98)+99的值
    # 最后一个是sum_number(0)
print sum_number(100)

运行结果:

5050

引申下一个面试题:

res = [lambda x:x+i for i in range(10)]
print res[0](10)

运行结果:

19

解释:

res其实就是[lambda x:x+i,lambda x:x+i,lambda x:x+i,lambda x:x+i,lambda x:x+i,lambda x:x+i,lambda x:x+i,lambda x:x+i,lambda x:x+i,lambda x:x+i]的列表。

res[0]就是取列表的第一个元素,就是–>lambda x:x+i(10)。匿名函数传递参数10,传递给参数x,i的值就是最上面定义的for i in range(10)。
函数在调用的时候才去查找变量,res[0]相当于lambda x:x+i,要求中res[0](10)的10就是传入x的值。i的值在遍历最后的值是9,所以引用i的值就是9。

递归小坑

在写百度子域名采集的时候,因为百度经常会返回一些失败的页面,所以需要对访问百度的函数进行递归操作,直到返回正确的页面。但是发现在递归函数得到正确页面,返回的结果却是None,找了一下资料,才明白递归的本质原理是酱紫的:

解释文章

主要的原因是函数调用中的堆栈进出顺序,比如:

运行递归函数1
函数1不是想要的结果...
运行递归函数2
函数2不是想要的结果....
运行递归函数3
递归函数3是想要的结果...
准备返回函数3的结果
函数3的结果返回到函数2
函数2没有想要的结果....
返回None

解决方法是返回递归函数的返回结果

即在函数1不是想要的结果.....
执行函数2的时候.....
返回函数1

用代码写出来就是

def test(x):
    if x<10:
        x+=1
        test(x)
    else:
        return x

改成

def test(x):
    if x<10:
        x+=1
        return test(x)
    else:
        return x

Python面试题