函数-递归调用、匿名
一、什么是递归调用
递归调用:在函数调用过程中,直接或间接地调用了函数本身,这就是函数的递归调用
1.递归的优点
递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。
使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。可以试试fact(1000)
:
2.递归的缺点
解决递归调用栈溢出的方法是通过尾递归优化,事实上尾递归和循环的效果是一样的,所以,把循环看成是一种特殊的尾递归函数也是可以的。
尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。
3.递归案例
#阶乘计算 def fact(n): if n==1: return 1 return n * fact(n - 1)
分析 ===> fact(5) ===> 5 * fact(4) ===> 5 * (4 * fact(3)) ===> 5 * (4 * (3 * fact(2))) ===> 5 * (4 * (3 * (2 * fact(1)))) ===> 5 * (4 * (3 * (2 * 1))) ===> 5 * (4 * (3 * 2)) ===> 5 * (4 * 6) ===> 5 * 24 ===> 120
4.二分法
#二分法 l = [1, 2, 10,33,53,71,73,75,77,85,101,201,202,999,11111] def search(find_num,seq): if len(seq) == 0: print('not exists') return mid_index=len(seq)//2 mid_num=seq[mid_index] print(seq,mid_num) if find_num > mid_num: #in the right seq=seq[mid_index+1:] search(find_num,seq) elif find_num < mid_num: #in the left seq=seq[:mid_index] search(find_num,seq) else: print('find it')
二、匿名函数
当我们在传入函数时,有些时候,不需要显式地定义函数,直接传入匿名函数更方便。
在Python中,对匿名函数提供了有限支持。还是以map()
函数为例,计算f(x)=x2时,除了定义一个f(x)
的函数外,还可以直接传入匿名函数:
通过对比可以看出,匿名函数lambda x: x * x
实际上就是:
def f(x): return x * x
关键字lambda
表示匿名函数,冒号前面的x
表示函数参数。
匿名函数有个限制,就是只能有一个表达式,不用写return
,返回值就是该表达式的结果。
用匿名函数有个好处,因为函数没有名字,不必担心函数名冲突。此外,匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数:
f = lambda x: x * x f(5) 结果25
同样,也可以把匿名函数作为返回值返回,比如:
def build(x, y): return lambda: x * x + y * y
三、max、min、lambda
1.max、min、lambda
salaries={ 'egon':3000, 'alex':100000000, 'wupeiqi':10000, 'yuanhao':2000 } print(max(salaries.values())) res=zip(salaries.vaues(),salaries.key()) print(max(res)) 结果(100000,alex)
salaries={ 'egon':3000, 'alex':100000000, 'wupeiqi':10000, 'yuanhao':2000 }
print(max(salaries,key=lambda k:salaries[k]))#salarier每次迭代将字典的k值赋值给k print(min(salaries,key=lambda k:salaries[k]))#salarier每次迭代将字典的k值赋值给k
print(sorted(salaries,key=lambda x:salaries[x])) 每次迭代将字典的k值赋值给x,默认是最小到大
print(sorted(salaries,key=lambda x:salaries[x],reverse=True)) #加reverse参数 True从大到小
2.global
#应用 x=1000 def f1(): global x#如果使用关键字global那么此时使用函数内定义的x x=0 f1() print(x) 结果 x=0
3.map应用
l=["1",'2','3'] res=map(lambda x:x+'sb',l)#迭代l列表并将每个元素加一个sb print(list(res)) 结果: ['1sb', '2sb', '3sb'] 求每个值得平方 nums=(1,2,3,4) res=map(lambda x:x**2,nums) print(linst(res))
4.reduce
l=[1,2,3,4] print(reduce(lambda x,y:x+y,l))#先拿到一个初始值然后然后和后边的值累加 #带初始值的 print(reduce(lambda x,y:x+y,l,10))如果初始值是10的话那么每次结果跟10相加
5.filter
l=[1,2,3,4] fes=filter(lambda x:x>2,l) print(list(fes)) l=("hanhan_s","li_s") fes=filter(lambda x:x.endswith("s"),l)