欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 金融 > 5.3 Python 闭包函数,递归函数,匿名函数

5.3 Python 闭包函数,递归函数,匿名函数

2024/11/30 12:52:10 来源:https://blog.csdn.net/qq_46137324/article/details/139658519  浏览:    关键词:5.3 Python 闭包函数,递归函数,匿名函数

1. 函数对象

Python中所有的数据都是对象, 函数的值也是一个对象, 通过函数名获取函数对象.
使用函数名也就是使用函数对象, 函数对象加上括号立刻执行函数体代码块.
函数名的其它作用:
* 1. 函数名可以作为其它变量的值.
* 2. 函数名可以作为其它函数的参数.
* 3. 函数名可以作为函数的返回值.
* 4. 函数名可以作为容器类型的的元素.
1.1 引用函数变量
# 检测代码, 申请内存地址存储函数体代码块, 并将函数体代码块的内存地址绑定给标识符func1.
def func1():print('1')# func2 引用 func1的内存地址, 也就是函数体代码块的内存地址.
func2 = func1
# 加括号调用
func2()
1.2 做为参数
# 检测代码, 申请内存地址存储函数体代码块, 并将函数体代码块的内存地址绑定给标识符func1.
def func1():print('1')def func2(func):# 调用func1函数func1()  # 1# 函数名func1最为另一个函数的参数
func2(func1)
# 省略写法, 语句不明确, 不推荐.
def func1():print('1')def func2():# 可以直接使用到外部的名称func1()func2()
1.3 做为返回值
# 检测代码, 申请内存地址存储函数体代码块, 并将函数体代码块的内存地址绑定给标识符func1.
def func1():print('1')def func2():# 直接可以使用到外部的名称return func1func = func2()
func()  # 1
从外部范围隐藏名称xx.
Pycharm的提示需要重命名参数名称来消除这个警告.

2022-12-11_01679

# 取消从外部范围隐藏名称提示.
def func1():print('1')def func2(fun_p):# 直接可以使用到外部的名称return fun_pfunc = func2(func1)
func()  # 1
# 省略写法, 语句不明确, 不推荐.
def func1():print('1')def func2():# 直接可以使用到外部的名称return func1func = func2()
func()  # 1
1.4 做为容器元素
# 检测代码, 申请内存地址存储函数体代码块, 并将函数体代码块的内存地址绑定给标识符add_staff.
def add_staff():print('添加员工')# 检测代码, 申请内存地址存储函数体代码块, 并将函数体代码块的内存地址绑定给标识符del_staff.
def del_staff():print('删除员工')func_dic = {'1': add_staff, '2': del_staff}# 获取元素得到函数对象, 加上括号执行函数体代码.
func_dic['1']()  # 添加员工
func_dic['2']()  # 删除员工

2. 函数嵌套

2.1 嵌套调用
在函数中调用其它函数.
def func1():print('form func1')def func2():func1()  # form func1print('form func2')func2()  # form func2
2.2 嵌套死循环
两个函数体内互相调用函数, 默认只有1000层嵌套, 可以设置源码修改默认嵌套层数, 超出就报错:
: RecursionError: maximum recursion depth exceeded.
: 递归错误:超过了最大递归深度.
def func1():# 在func1中调用func2func2()def func2():# 在func2中调用func1func1()# 启动
func2()

2022-12-11_01680

2.3 函数嵌套定义
函数嵌套定义: 一个函数里用def语句来创建其它的函数的情况.
目的: 将复杂的功能全部隐藏, 暴露一个接口, 供操作者使用,
操作者不需要明白内部的代码是干什么的, 只需要知道接口的功能, 和使用方法即可.
def all_func(choices):def add_staff():print('添加员工')def find_only():print('查询员工')def modify_salary():print('修改薪资')def all_staff():print('所有信息')def del_staff():print('删除员工')func_dic = {'1': add_staff,'2': find_only,'3': modify_salary,'4': all_staff,'5': del_staff,}if choices in func_dic:func_dic[choices]()else:print('功能为开放!')while True:print("""1. 添加员工2. 查询员工3. 修改薪资4. 所有信息5. 删除员工""")choice = input('请输入编号>>>:')all_func(choice)

3. 闭包函数

闭包函数 = 函数对象 + 函数嵌套定义 + 名称空间与作用域.
闭包函数满足以下两个条件:
* 1. 闭函数: 定义在函数内部的函数, 闭包函数是一种为函数传参的方案.
* 2. 包函数: 内部局部函数引用了外层局部函数的名称.
3.1 直接传参
def func(x, y):print(x, y)func(1, 2)
3.2 闭包函数传参
# 演变过程1
def func1():x = 1y = 2def func2():# 在函数内部使用外部的函数的名称print(x, y)  # 1 2return func2func = func1()
func()
# 演变过程2
def func1(x, y):def func2():print(x, y)  # 1 2return func2func = func1(1, 2)
# 闭包函数
func()

4. 递归函数

递归函数: 在运行过程中直接或间接的调用自己, 一种基于函数实现循环.
默认嵌套1000, 超出报错, 可以设置参数修改嵌套层次, 某些电脑可能只能达到99?层.
递归是要有一定条件的:
* 1. 每次递推之后复杂度相较于上一次一定要有所下降.
* 2. 必须要能回溯.递归分两步:
* 1. 递推: 一层层往下推导结果, 递推满足某个条件后, 开始回溯.
* 2. 回溯: 依据最后的结果回溯得到最初问题的答案.
4.1 示例1
推导第一个个小孩子的年龄:
现在有五个小朋友: 1 2 3 4 5          递推总次数 count = 5    
第一个小朋友说比第二个小朋友大 2          count - 1   + 2 
第二个小朋友说比第三个小朋友大 2          count - 1   + 2 
第三个小朋友说比第四个小朋友大 2          count - 1   + 2 
第四个小朋友说比第五个小朋友大 2          count - 1   + 2 
第五个小朋友18                          count = 0  return 18   回溯 

image-20221212054838441

def get_age(count):count -= 1  # 递推重做的事if count == 0:  # 回溯的条件return 18return get_age(count) + 2  # 回溯放回重复做的事print(get_age(5))
# 省略写法
def get_age(count):if count == 1:return 18# 在这一步开始执行函数return get_age(count - 1) + 2  print(get_age(5))  # 26
4.2 示例2
打印出列表中每一个整型元素.
list1 = [1, [2, [3, [4, [5, [6, [7, [8, [9, [10, [11, [12, [13, [14, ]]]]]]]]]]]]]]
list1 = [1, [2, [3, [4, [5, [6, [7, [8, [9, [10, [11, [12, [13, [14, ]]]]]]]]]]]]]]def print_element(l1):# 遍历列表for i in l1:# 元素是整型则打印if type(i) == int:print(i)# 全是是嵌套列表, 则继续递归处理列表else:print_element(i)print_element(list1)
4.3 示例3
算法: 解决问题的最高效方式.
使用递归二分法快速找出序列序列的某个值. 查找的元素就在数据集的头尾那么该算法不是很高效.list1 = [11, 23, 43, 57, 68, 76, 81, 99, 123, 321, 432, 567, 666, 712, 899, 999, 1111]
将列表从中间一分为二, 判断中间的值, 比查找的值大还是小.
在每次的二分之一基础上筛选掉一半的值, 找到最后, 要么存在要么不存在.
l1 = [11, 23, 43, 57, 68, 76, 81, 99, 123, 321, 432, 567, 666, 712, 899, 999, 1111]# 查找的值
num = 23# 获取中间的值的索引, 整除
def find_num(list1, num):if not list1:print('没有这个数据')return# 获取中间值average = len(list1) // 2if list1[average] < num:# 获取右边的列表r_list = list1[average + 1:]find_num(r_list, num)elif list1[average] > num:# 获取右边的列表l_list = list1[:average]find_num(l_list, num)else:print('找到了')returnfind_num(l1, num)
l1 = [11, 23, 43, 57, 68, 76, 81, 99, 123, 321, 432, 567, 666, 712, 899, 999, 1111]def find_num(list1, num):# 结束条件 列表为空if len(list1) == 0:print('查找的数字不存在!')return# 定义一个中间值middle = len(list1) // 2  # 只能是整除 1//2 = 0print(middle, list1[middle], num)# 输入的值与中间值做比较if num < list1[middle]:# 比中间值小向 往列表的左←边查找list1 = list1[0:middle]find_num(list1, num)# 比中间值大向 往列表的右→边查找elif list1[middle] < num:list1 = list1[middle + 1:]find_num(list1, num)# 不大不小就找到了.else:print('找到了')returninput_num = int(input('输入查找的数字>>>:').strip())
find_num(l1, input_num)

5. 匿名函数

匿名函数: 指没有名字的函数, 通常只使用一次, 在需要一个函数, 但是又不想思考起名字时使用.
一般不会单独使用, 都是配合其他函数一起使用.
格式: lambda 形参: 计算返回值的表达式
返回形参处理的结果.
# 加上括号调用,  括号内传入参数
print((lambda x: x ** 2)(2))  
为匿名函数起名字, 会提示不规范:
: PEP8: E731 do not assign a lambda expression, use a def.
: PEP8: E731不指定lambda表达式,请使用def.
# 会出现PEP8提示
func = lambda x: x ** 2
res = func(2)
print(res)  # 4

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com