(十五)Python学习之函数、递归、高级函数
一、递归调用
1.概念:
在函数内部,可以调用其他函数;如果在调用一个函数的过程中直接或间接调用自身本身称为递归调用。
2.递归特性:
(1)必须有一个明确的结束条件;
(2)每次进入更深一层递归时,问题规模相比上次递归都应有所减少;
(3)递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)。
def calc(n):
print(n)
if int(n / 2) == 0:
return n
return calc(int(n / 2))
calc(10)
二、函数的作用域
函数作用域在定义函数时就已经固定住了,不会随着调用位置的改变而改变。
三、匿名函数
1.含义:
匿名函数就是不需要显式的指定函数;
2.形式及说明:
lambda [arg1 [,arg2,.....argn]]:expression
lambda 参数列表:return [表达式] 变量
由于lambda返回的是函数对象(构建的是一个函数对象),所以需要定义一个变量去接收;
res = map(lambda x: x ** 2, [1, 5, 7, 4, 8])
for i in res:
print(i)
三、编程的方法论
1.面向过程
2.函数式
3.面向对象
四、尾调用与尾递归
1.尾调用定义:
在函数的最后一步调用另外一个函数(最后一行不一定是函数的最后一步)
2.尾调用优化:
尾调用之所以与其他调用不同,就在于它的特殊的调用位置。函数调用会在内存形成一个"调用记录",又称"调用帧"(call frame),保存调用位置和内部变量等信息。如果在函数A的内部调用函数B,那么在A的调用记录上方,还会形成一个B的调用记录。等到B运行结束,将结果返回到A,B的调用记录才会消失。如果函数B内部还调用函数C,那就还有一个C的调用记录栈,以此类推。所有的调用记录,就形成一个"调用栈"(call stack)。尾调用由于是函数的最后一步操作,所以不需要保留外层函数的调用记录,因为调用位置、内部变量等信息都不会再用到了,只要直接用内层函数的调用记录,取代外层函数的调用记录就可以了。这就叫做"尾调用优化"(Tail call optimization),即只保留内层函数的调用记录。如果所有函数都是尾调用,那么完全可以做到每次执行时,调用记录只有一项,这将大大节省内存。
3.尾递归定义:
函数调用自身,称为递归。如果尾调用自身,就称为尾递归。
4.尾递归优化:
递归非常耗费内存,因为需要同时保存成千上百个调用记录,很容易发生"栈溢出"错误(stack overflow)。但对于尾递归来说,由于只存在一个调用记录,所以永远不会发生"栈溢出"错误。
五、高阶函数
1.定义:
满足俩个特性任意一个即为高阶函数
(1)函数的传入参数是一个函数名;
(2)函数的返回值是一个函数名。