函数装饰器
装饰器的作用:在函数名以及函数体不改变的前提下,给一个函数附加一些额外的代码
以下案例 层层递进 当然也可以看完案例一直接看案例五,六
案例:发说说,发图片
用案例来说明更清晰
案例一
普通实现方法
# 定义两个功能函数
def fss():
print("发说说")
def ftp():
print("发图片")
# 相关的逻辑代码
btnIndex = 1
if btnIndex == 1:
print('登录验证...')
fss()
else:
print('登录验证...')
ftp()
# 发说说,发图片,必须有一个前提,就是,用户必须登录之后
# 所以建议增添登录验证的操作
# 方式一:直接在业务逻辑代码里面去修改,添加一个验证操作
# 因为业务逻辑代码非常多,所以,就造成了,每一份逻辑代码在调用具体的功能函数之前,
# 都需要去做一个登录验证,代码冗余度打比较大,代码的复用性比较差,代码的维护性比较差
登录验证...
发说说
案例二
方式二:直接在功能函数里面取去修改,方便代码的重用
定义两个功能函数
def fss():
print('登录验证...')
print("发说说")
def ftp():
print('登录验证...')
print("发图片")
# 相关的逻辑代码
btnIndex = 1
if btnIndex == 1:
fss()
else:
ftp()
登录验证...
发说说
案例三
进一步缩减代码冗余度
定义两个功能函数
# 进一步缩减代码冗余度
# 定义两个功能函数
def fss():
checkLogin()
print("发说说")
def ftp():
checkLogin()
print("发图片")
def checkLogin():
print('登录验证...')
# 相关的逻辑代码
btnIndex = 1
if btnIndex == 1:
fss()
else:
ftp()
登录验证...
发说说
案例四
继续优化代码
def fss():
print("发说说")
def ftp():
print("发图片")
def checkLogin(func):
print('登录验证...')
func()
# 相关的逻辑代码
btnIndex = 1
if btnIndex == 1:
checkLogin(fss)
else:
checkLogineckLogin(ftp)
登录验证...
发说说
案例五
这里的checkLogin就是装饰器
# 这里的checkLogin就是装饰器
def checkLogin(func):
def inner():
print('登录验证...')
func()
return inner
def fss():
print("发说说")
def ftp():
print("发图片")
fss = checkLogin(fss)
ftp = checkLogin(ftp)
# 相关的逻辑代码
btnIndex = 1
if btnIndex == 1:
fss()
else:
ftp()
登录验证...
发说说
案例六
装饰器简化写法(python写法)
# 这里的checkLogin就是装饰器
def checkLogin(func):
def inner():
print('登录验证...')
func()
return inner
@checkLogin
def fss():
print("发说说")
@checkLogin
def ftp():
print("发图片")
btnIndex = 2
if btnIndex == 1:
fss()
else:
ftp()
登录验证...
发图片
补充:装饰器是立刻执行
# 这里的checkLogin就是装饰器
def checkLogin(func):
print('装饰器是立刻执行!!!')
def inner():
print('登录验证...')
func()
return inner
print('装饰器第一次执行: ',end='')
@checkLogin
def fss():
print("发说说")
print('装饰器第二次执行: ',end='')
@checkLogin
def ftp():
print("发图片")
print('装饰器执行了两次')
btnIndex = 2
if btnIndex == 1:
fss()
else:
ftp()
装饰器第一次执行: 装饰器是立刻执行!!!
装饰器第二次执行: 装饰器是立刻执行!!!
装饰器执行了两次
登录验证...
发图片
注意事项
装饰器的叠加
从上到下装饰
从下到上执行
def zsq_bdk(func):
def inner():
print('背带裤')
func()
return inner
def zsq_dlq(func):
def inner():
print('打篮球')
func()
return inner
def zsq_jntm(func):
def inner():
print('姬霓太美')
func()
return inner
@zsq_bdk
@zsq_dlq
@zsq_jntm
def cxk():
print('社会我kun哥,人狠才艺多')
cxk()
背带裤
打篮球
姬霓太美
社会我kun哥,人狠才艺多
对有参数的函数进行装饰
怎么装包就怎么拆包
def zsq(func):
# 装包
def inner(*args, **kwargs):
print("*"*30)
# print(args,kwargs)
# 拆包
func(*args,**kwargs)
return inner
# punum = zsq(pnum)
@zsq
def pnum1(num1,num2):
print(num1,num2)
@zsq
def pnum2(num):
print(num)
pnum1(123,456)
pnum2(999)
******************************
123 456
******************************
999
对有返回值的函数进行装饰
def zsq(func):
# 装包
def inner(*args, **kwargs):
print("*"*30)
res = func(*args,**kwargs)
return res
return inner
# punum = zsq(pnum)
@zsq
def pnum1(num1,num2):
print(num1,num2)
return num1+num2
@zsq
def pnum2(num):
print(num)
res1 = pnum1(123,456)
pnum2(999)
print(res1)
******************************
123 456
******************************
999
579
带有参数的装饰器
先计算@后面的内容,把这个内容当做是装饰器本身
def getzsq(char):
def zsq(func):
def inner():
print(char*30)
func()
return inner
return zsq
char = input('请输入一个字符')
@getzsq(char)
def f1():
print('666')
f1()
请输入一个字符*
******************************
666
类装饰器
class check:
def __init__(self, func):
self.f = func
def __call__(self, *args, **kwargs):
print('登录验证')
self.f()
@check
# fss = check(fss)
def fss():
print("发说说")
fss()
登录验证
发说说