多层语法糖
def outter1(func1):
print('加载了outter1')
def wrapper1(*args, **kwargs):
print('执行了wrapper1')
res1 = func1(*args, **kwargs)
return res1
return wrapper1
def outter2(func2):
print('加载了outter2')
def wrapper2(*args, **kwargs):
print('执行了wrapper2')
res2 = func2(*args, **kwargs)
return res2
return wrapper2
def outter3(func3):
print('加载了outter3')
def wrapper3(*args, **kwargs):
print('执行了wrapper3')
res3 = func3(*args, **kwargs)
return res3
return wrapper3
@outter1 # outter1拿到wrapper2,outter1的上层没有语法糖,index = outter1(wrapperw)
@outter2 #outter2拿到wrapper3,wrapper3 = outter3(index)
@outter3 #@outter3紧贴index(),outter3调用index(),返回wrapper3,所以wrapper3 = outter3(index)
def index():
print('from index')
多层语法糖加载的顺序从下往上执行,
每次执行之后如果上面还有语法糖 则直接将返回值函数名传给上面的语法糖
如果上面没有语法糖了 则变形 index = outter1(wrapper2)
有参装饰器
def outter(x):
def outter1(func):
def wrapper(*args,*kwargs):
res = func(*args,**kwargs)
print(x)
return res
return wrapper
return outter1
# 通过第三层进行传值,使得有参装饰器可以使用其他参数,实现其他功能。
@outter('a')
#可以被看做
#f1 = outter1(f1)
#f1 = wrapper(*args,**kwargs)
装饰器模板
最常用的无参装饰器
def outer(func_name):
def inner(*args, **kwargs):
res = func_name(*args, **kwargs)
return res
return inner
@outer
def index():
pass
不常用的有参装饰器
def outer_plus(mode):
def outer(func_name):
def inner(*args, **kwargs):
res = func_name(*args, **kwargs)
return res
return inner
return outer
@outer_plus('MySQL')
def func():
pass
装饰器修复技术
由来:使用装饰器有一个小毛病,就是想要查看被装饰器的注释或者名字时,比如使用如下方法时:
print(help(index)) # 查看函数的注释
print(index.__name__) # 查看函数名字符串形式
结果看到的注释不是被装饰器的注释,而是装饰器里面的内部闭包函数的注释。
查看到的函数名字也是装饰器内部函数的名字,调用函数的时候,想看函数的名字和注释,看到的却不是对的。
基于以上情况,Python提供了解决方案,叫做装饰器修复技术。
# def index():
# """index函数 非常的牛"""
# pass
# help(index)
# help(len)
from functools import wraps
def outer(func_name):
@wraps(func_name) # 仅仅是为了让装饰器的效果更加逼真 平时可以不写
def inner(*args, **kwargs):
"""我是inner 我擅长让人蒙蔽"""
res = func_name(*args, **kwargs)
return res
return inner
@outer
def func():
"""我是真正的func 我很强大 我很牛 我很聪明"""
pass
# help(func)
# print(func)
func()
递归函数
递归的特点:
函数内部自己调用自己。
必须有出口。
1 必须有一个明确的结束条件。
2 每次进入更深一层递归时,问题规模(计算量)相比上次递归都应有所减少。
3 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出),此时程序会抛出错误:超出最大递归深度。
递推:像上边递归实现所拆解,递归每一次都是基于上一次进行下一次的执行,这叫递推。
回溯:则是在遇到终止条件,则从最后往回返一级一级的把值返回来,这叫回溯。
eg:
#1直接调用
# def index():
# print('from index')
# index()
# index()
# 间接
# def index():
# print('from index')
# func()
#
# def func():
# print('from func')
# index()
#
# func()
'''最大递归深度:python解释器添加的安全措施'''
# count = 0
# def index():
# global count
# count += 1
# print(count)
# index()
# index()
'''官网提供的最大递归深度为1000 我们在测试的时候可能会出现996 997 998'''
2.递归函数
"""
get_age(5) = get_age(4) + 2
get_age(4) = get_age(3) + 2
get_age(3) = get_age(2) + 2
get_age(2) = get_age(1) + 2
get_age(1) = 18
"""
def get_age(n):
if n == 1:
return 18
return get_age(n-1) + 2
res = get_age(5)
print(res)
作业
1.利用递归函数依次打印列表中每一个数据值
l1 = [1,[2,[3,[4,[5,[6,[7,[8,]]]]]]]]
def get_num(num):
for i in num: # 自带结束条件 并且每次传入的数据都比上一次简单
if isinstance(i, int): # 判断数据是否属于整型
print(i)
else:
get_num(i)
return num
get_num(l1)
3.利用有参装饰器编写多种用户登录校验策略
# 校验用户是否登录装饰器
a=1
def outer(mode):
#mode=1
def login_auth(func_name):
def inner(*args, **kwargs):
username = input('username>>>:').strip()
password = input('password>>>:').strip()
if mode == '1':
print('数据直接写死')
if username=='jason' and password=='123':
print('数据直接写死')
else:
print('登陆失败')
return outer(mode)
elif mode == '2':
print('数据来源于文本文件')
with open(r'a.txt','r+',encoding='utf8') as f:
for line in f:
real_name,real_password=line.split('|')
if username==real_name and real_password.strip('\n')==password:
print('登录成功')
else:
print('登陆失败')
elif mode == '3':
print('数据来源于字典')
user_dic={'name':'jason','password':'123'}
if user_dic.get('name')==username and user_dic.get('password')==password:
print('登录成功')
else:
print('登陆失败')
elif mode == '4':
print('数据来源于MySQL')
return inner
return login_auth
@outer('1')
def index():
print('from index')
index()
@outer('2')
def func():
print('from func')
func()
@outer('3')
def fun2():
print('from fun2')
fun2()
@outer('4')
def fun3():
print('from fun3')
fun3()