1. 函数对象
Python中所有的数据都是对象, 函数的值也是一个对象, 通过函数名获取函数对象.
使用函数名也就是使用函数对象, 函数对象加上括号立刻执行函数体代码块.
函数名的其它作用:
* 1. 函数名可以作为其它变量的值.
* 2. 函数名可以作为其它函数的参数.
* 3. 函数名可以作为函数的返回值.
* 4. 函数名可以作为容器类型的的元素.
1.1 引用函数变量
def func1():
print('1')
func2 = func1
func2()
1.2 做为参数
def func1():
print('1')
def func2(func):
func1()
func2(func1)
def func1():
print('1')
def func2():
func1()
func2()
1.3 做为返回值
def func1():
print('1')
def func2():
return func1
func = func2()
func()
从外部范围隐藏名称xx.
Pycharm的提示需要重命名参数名称来消除这个警告.
![2022-12-11_01679](https://img-blog.csdnimg.cn/img_convert/273b3348c63b133f6c67c77f6616613b.png)
def func1():
print('1')
def func2(fun_p):
return fun_p
func = func2(func1)
func()
def func1():
print('1')
def func2():
return func1
func = func2()
func()
1.4 做为容器元素
def add_staff():
print('添加员工')
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()
print('form func2')
func2()
2.2 嵌套死循环
两个函数体内互相调用函数, 默认只有1000层嵌套, 可以设置源码修改默认嵌套层数, 超出就报错:
英: RecursionError: maximum recursion depth exceeded.
中: 递归错误:超过了最大递归深度.
def func1():
func2()
def func2():
func1()
func2()
![2022-12-11_01680](https://img-blog.csdnimg.cn/img_convert/0aa1ae05c9930c6b2a2afbfd31d7fc1d.png)
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 闭包函数传参
def func1():
x = 1
y = 2
def func2():
print(x, y)
return func2
func = func1()
func()
def func1(x, y):
def func2():
print(x, y)
return func2
func = 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](https://img-blog.csdnimg.cn/img_convert/37f7f0dcab4e00eb330d94befc577149.png)
def get_age(count):
count -= 1
if count == 0:
return 18
return 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))
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) // 2
if 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('找到了')
return
find_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
print(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('找到了')
return
input_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.
func = lambda x: x ** 2
res = func(2)
print(res)