今日内容
多层装饰器
'''
语法糖的功能
会自动将下面紧挨着的函数名当做参数传递@符号后面的函数名(加括号调用)
涉及多个语法糖装饰一个函数名
从下往上执行 最后一个语法糖才会做重命名操作
'''
def outter1(func1): # func1 = wrapper2函数名
print('加载了outter1')
def wrapper1(*args, **kwargs):
print('执行了wrapper1')
res1 = func1(*args, **kwargs)
return res1
return wrapper1
def outter2(func2): # func = wrapper3函数名
print('加载了outter2')
def wrapper2(*args, **kwargs):
print('执行了wrapper2')
res2 = func2(*args, **kwargs)
return res2
return wrapper2
def outter3(func3): # func3 = 真正的index函数
print('加载了outter3')
def wrapper3(*args, **kwargs):
print('执行了wrapper3')
res3 = func3(*args, **kwargs)
return res3
return wrapper3
@outter1 # index = outter1(wrapper2)
@outter2 # wrapper2 = outter2(wrapper3)
@outter3 # wrapper3 = outter3(真正的函数名)
def index():
print('from index')
index()
执行结果
加载了outter3
加载了outter2
加载了outter1
执行了wrapper1
执行了wrapper2
执行了wrapper3
from index
有参装饰器
当你编写一个装饰器的时候 这个装饰器内部需要外界传入额外的数据来控制代码的一个分支 就需要给原来的装饰器模板在套一层 然后再用的给语法糖添加额外的数据 那么你的装饰器就跟原来的一模一样 这就是有参装饰器
# 需求:在使用装饰器进行用户校验时,我可以随意切换数据的来源,无论是字典、列表还是文件
# 1.先定义一个outer函数
def outer(condition): # 4.字典传给了condition
def login_auth(function_name): # 5.执行login_auth函数 无法添加更多的形参,只能接收一个被装饰对象的函数名
def inner(*args, **kwargs): # 无法添加参数,因为它是专门用来给被装饰器对象传参的
username = input('please your username>>>:').strip()
password = input('please your password>>>:').strip()
# 根据用户需求执行不同的代码
if condition == '字典':
print('使用字典作为用户数据来源,进行比对')
elif condition == '列表':
print('使用列表作为用户数据来源,进行比对')
elif condition == '文件':
print('使用文件作为用户数据来源,进行比对')
else:
print('其他操作情况')
return inner
return login_auth # 6.返回login_auth
@outer('字典') # 3.先看outer函数(),执行outer函数
def index(): # 2.定义一个index函数
print('hello word')
index()
概念
函数直接调用和间接调用
1.直接调用
def func():
print('from func')
func()
func()
2.间接调用
def func():
print('from func')
index()
def index():
print('from index')
func()
func()
'''python中允许函数最大的递归调用次数
官方给出的限制是1000 用代码去验证的话可能会有些许的误差(997,998...)
'''
def index():
print('from index')
global count
count += 1
print(count) # 998
index()
index()
import sys
# print(sys.getrecursionlimit()) # 1000
sys.setrecursionlimit(99999999) # 可以自定义最大的次数
print(sys.getrecursionlimit()) # 99999999
'''递归函数真正的应用场景
递推:一层一层往下寻找答案
回溯:根据已知条件推导最终的结果
递归函数
1.递归函数每次调用的时候都必须要比上一次简单
2.并且递归函数最终都必须要有一个明确的结束条件
'''
l1 = [1, [2, [3, [4, [5, [6, [7, [8, [9, [10]]]]]]]]]]
# 循环打印列表中所有的数字
# 首先我们能想到的是for循环
for i in l1:
if isinstance(i,int): # 判断i所绑定的数据值是否是整型
print(i)
else:
for j in i:
if isinstance(j,int):
print(j)
else:
for k in j:
if isinstance(k,int):
print(k)
这样写的话会重现很多重复的代码 为了减少重复性我们可以把代码封装成函数
def get_num(l1): # 定义一个函数
for i in l1:
if isinstance(i, int): # 判断i所绑定的数据值是否是整型
print(i)
else:
get_num(i) # 调用函数传用实参i
get_num(l1)
使用递归函数可以减少很多重复的代码
算法之二分法
算法就是能解决一些问题的方法
算法永远都在精进 但是很少有最完美的算法
二分法
是所有算法里面最简单的算法
也有人说二分法不是算法
# 定义一个函数
def index(l1, target_num):
if len(l1) == 0: # 要有一个明确的结束条件 列表数据值为0 结束
print('没找到')
return
middle_index = len(l1) // 2 # 取出列表中间的数
middle_value = l1[middle_index]
if target_num > middle_value: # 判断中间数据值与目标数据值谁大谁小
right_l1 = l1[middle_index + 1:] # 要查找的目标数据值在右 切取右边
print(right_l1)
index(right_l1, target_num)
elif target_num < middle_value:
left_l1 = l1[:middle_index] # 要查找的目标数据值在左 切取左边
print(left_l1)
index(left_l1, target_num) # 递归函数
else:
print('找到了', target_num)
index(l1, 999)
课后作业
# 2.尝试编写递归函数
# 推导指定某个人的正确年龄
# eg: A B C D E 已知E是18 求A是多少
def age(n): # 定义一个函数
if n == 1:
return 18 # 返回的是年龄
else:
return age(n-1) + 2 # 年龄从后往前面加
a = age(5)
print(a)