Python-有参装饰器

一、知识储备
核心:wrapper的参数不能动,outter的参数也不能动

由于语法糖@的限制,outter函数只能有一个参数,并且该参数只是用来接收被装饰对象的内存地址
def outter(func):
def wrapper(*args,**kwargs): #1.调用原函数 2.为其增加新功能


res=func(*args,**kwargs) #func()参数要写活,所以func(*args,**kwargs)
return res
return wrapper


@outter #index=outter(index) index=wrapper
def index(x,y):
print("index...%s %s"%(x,y))

index(1,2)

偷梁换柱之后:
1.index的参数是什么样子,wrapper的参数就应该什么样子
2.index的返回值是什么样子,wrapper的返回值就应该什么样子
3.index的属性是什么样子,wrapper的属性就应该什么样子----> from import functools import wraps


二、案例需求:实现账号密码认证,认证成功之后执行被装饰对象函数
三炮玩法
'''
def auth(func,verify_type): #auth函数形参中加了verify_type参数就不能使用语法糖了
def wrapper(*args,**kwargs): #1.调用原函数 2.为其增加新功能
#区分验证,wrapper函数内需要一个参数,不能通过wrapper函数形参传参进来.外面还有一层auth函数,在auth函数形参中加一个参数,wrapper函数内是可以访问到的
Input_User = input("请输入账号:").strip()
Input_Pass = input("请输入密码:").strip()
if verify_type == 'file':
print("基于文件验证!")
if Input_User == "llj" and Input_Pass =="123":
print("输入账号密码正确!")
res=func(*args,**kwargs) #func()参数要写活,所以func(*args,**kwargs)
return res
else:
print("输入账号密码错误!")
elif verify_type == 'db':
print("基于数据库验证")
elif verify_type == 'ladp':
print("基于ladp验证")
else:
print("不支持!")
return wrapper

基于文件的验证
#@auth 不能使用语法糖
def index(x,y):
pass

index=auth(index,'file')
index(1,2)


基于数据库的验证
#@auth 不能使用语法糖
def home(name):
pass

home=auth(home,'db')
home('llj')

基于ladp的验证
#@auth 不能使用语法糖
def ladp(name):
pass

#ladp=auth(ladp,'ladp')
#ladp('llj')

'''


语法糖
使用闭包函数为函数体传参:deco函数内需要verify_type参数,目前deco函数在全局,包起来之后,需要把deco放回全局的
def auth(verify_type):
def deco(func): #使用语法糖 auth函数参数限制再多加一个形参参数
def wrapper(*args,**kwargs): #1.调用原函数 2.为其增加新功能 #wrapper这块参数不能动
#区分验证
Input_User = input("请输入账号:").strip()
Input_Pass = input("请输入密码:").strip()
if verify_type == 'file':
print("基于文件验证!")
if Input_User == "llj" and Input_Pass =="123":
print("输入账号密码正确!")
res=func(*args,**kwargs) #func()参数要写活,所以func(*args,**kwargs)
return res
else:
print("输入账号密码错误!")
elif verify_type == 'db':
print("基于数据库验证")
elif verify_type == 'ladp':
print("基于ladp验证")
else:
print("不支持!")
return wrapper
return deco
 
基于文件的验证
deco=auth(verify_type='file')
@deco
def index(x,y):
pass

index(1,2)


基于数据库的验证
deco=auth(verify_type='mysql')
@deco
def home(name):
pass

home('llj')


基于ladp的验证
deco=auth(verify_type='ladp')
@deco
def ladp(name):
pass

ladp('llj')


针对上面使用语法糖优化
基于文件的验证
#deco等于auth(verify_type='file')直接@auth(verify_type='file')
@auth(verify_type='file') #碰到@auth()直接运行auth函数体代码,合起来auth函数代码体,只有三行代码,运行完最后一行代码返回deco的内存地址 即@deco
#遇到@doco把正下方函数内存地址放进来,赋值给index 即index=deco(index) 调用index是调用wrapper 即index=wrapper
#调用deco把deco函数打开,里面只有三行代码.返回wrapper
#调用wrapper把wrapper函数打开,传进来参数wrapper(1,2).wrapper函数内需要verify_type参数,通过auth函数参数传进来

def index(x,y):
pass
index(1,2)  #wrapper(1,2)


基于数据库的验证
@auth(verify_type='mysql')
def home(name):
pass

home('llj')

基于ladp的验证
@auth(verify_type='ladp')
def ladp(name):
pass

ladp('llj')



有参装饰器的模板
def 有参装饰器(x,y,z):
def outter(func):
def wrapper(*args,**kwargs): #1.调用原函数 2.为其增加新功能
res=func(*args,**kwargs) #func()参数要写活,所以func(*args,**kwargs)
return res
return wrapper
return outter

@有参装饰器(1,2,3)
def index(a,b,c):
pass
 
 
 
posted @ 2020-11-16 14:32  梁博客  阅读(111)  评论(0)    收藏  举报