本文在上一篇文章:python函数式编程基础(一)的基础上继续介绍函数的闭包概念,递归以及高阶函数
python函数式编程基础(一):https://blog.csdn.net/Geroge_lmx/article/details/80740484
回顾:闭包是一个内嵌函数引用了外部嵌套函数的变量,并且外部嵌套函数返回的是内嵌函数
准备知识:局部变量,全局变量以及作用域
一.变量及作用域
局部变量:
1.定义在函数内部的变量,函数的形参也属于局部变量
2.只能在函数内部使用
3.在函数调用时被创建,调用结束后自动销毁
全局变量:
1.定义在函数外部,模块内部的变量
2.所有的函数都可以直接“访问”全局变量
3.对于不可变数据类型,函数内部不能直接通过赋值语句来改变全局变量
4.对于可变数据类型,函数内部可以直接通过赋值语句来改变全局变量
python的作用域:LEGB
做用域也叫命名空间,是访问变量时查找变量名的范围空间
L(local):局部作用域(函数内)
E(Enclosing):外部嵌套函数作用域
G(Globals):全局作用域(模块内)
B(Builtin):python内置模块的作用域
变量名查找顺序:
查找顺序:L --> E --> G --> B
global 语句:
作用:
全局声明,将函数内部赋值的变量映射到全局作用域
语法:
global 变量1, 变量2, ...
说明:
1.在函数内部修改绑定不可变数据类型的全局变量时,必须用global声明,否则将被视为局部变量
2.全局变量在函数内部可以不经过声明直接访问
3.禁止先创建局部变量,再用global声明为全局变量
nonlocal语句:
作用:nonlocal声明,变量不是局部变量,而是外部嵌套函数内的变量语法:
nonlocal 变量1,变量2
说明:
1.nonlocal语句只能在内嵌函数内使用
2.访问nonlocal变量将对外部嵌套函数作用域内的变量产生影响
3.当有2层或2层以上的函数嵌套时,访问nonlocal变量只对最近一层的变量进行操作
二.闭包
闭包的三个条件:
1.必须有内嵌函数2.内嵌函数必须引用外部函数中的变量
3.外部函数返回值必须是“内嵌函数”
通常情况下,在函数调用结束后,函数内部变量会自动被释放掉。但闭包不同,如果外部嵌套函数在调用结束后,发现自己的变量在内嵌函数中有使用,则外部函数在调用结束后,在返回内嵌函数的同时,也会将这些变量传递给内嵌函数,一起绑定起来。这样,外部函数调用结束后,内嵌函数被调用时仍可以访问外部嵌套函数作用域内的变量。如下:
def outer(start): step1 = 1 step2 = [1] def iner(): #修改enclosing变量必须进行声明,告诉解析器step不是局部变量,而是enclosing变量 nonlocal step1 sum_num1 = start + step1 #仅访问start的值,而不做修改,故start无需声明 sum_num2 = start + step2[0] #对于可变数据类型,无需声明 print('start + step1 = %d' % sum_num1) print('start + step2[0] = %d' % sum_num2) step1 += 1 step2[0] += 2 return iner a1 = outer(10) a1() print('-------------------') a1() print('-------------------') a1() 运行结果: start + step1 = 11 start + step2[0] = 11 ------------------- start + step1 = 12 start + step2[0] = 13 ------------------- start + step1 = 13 start + step2[0] = 15
三.递归函数 Recursion
1.函数直接或间接地调用自身,如:
def func(): '''直接调用自己,进入递归''' func() func() def func1(): '''函数间接调用自身''' func2() def func2(): func1() func1() print("递归完成")2.备注:
1.递归一定要控制递归的层数,当符合一定条件时,要终止递归调用;
2.几乎所有的递归,都能用while循环来代替
3.每次调用函数时,都会开辟一块独立的空间
3.优点:
简化问题,思路清晰,代码简洁(在适合使用递归地问题上,使用递归)
4.缺点:
递归因系统环境影响大,当递归深度太大时,可能会得到不可预知的结果
备注:
1.递归深度默认为1000
2.sys.getrecursionlimit()--->可以查看递归深度
3.sys.setrecursionlimit(n)--->可以修改递归深度
5.递归的两个阶段:
递推阶段:
由问题出发,从未知到已知,按递归公式递推,直到满足终止条件。
回归阶段:
由递归终止条件得到的结果出发,逆向逐步代入递归公式,回归问题。
6.递归的实现方法:
先假设函数已经实现
7.实例:
①计算等差数列1,2,3...n的和
def mysum(n): if n == 1: return 1 return n + mysum(n-1) print(mysum(100)) 运行结果: 5050
②写一个函数求n的阶乘
def myfac(n): '''函数递归调用''' if n==1: return 1 return n * myfac(n-1) print('5的阶乘是:', myfac(5)) 运行结果: 5的阶乘是: 120
③L = [[3, 5, 8], 10, [[13, 14], 15, 18], 20]
1) 递归打印列表内的所有元素
2) 计算列表中所有元素的和
def print_list(L): for item in L: if type(item) is not list: print(item,end=' ') else: print_list(item) #递归的思想 def sum_list(L): sum_number = 0 for item in L: if type(item) is not list: sum_number += item else: sum_number += sum_list(item) return sum_number L = [[3, 5, 8], 10, [[13, 14], 15, 18], 20] print_list(L) print() print("返回这个列表中所有元素的和:", sum_list(L))