叠加装饰器和补充部分
叠加装饰器
叠加装饰器:
在同一个被装饰对象中,添加多个装饰器,并执行。
@装饰1
@装饰2
@装饰3
def 被装饰对象():
pass
注意:装饰器在调用被装饰对象时才会执行添加新功能。
- 叠加装饰器:
- 装饰的顺序: 由下到上装饰
- 执行的顺序: 由上往下
注意:无论inner中出现让任何的判断,最后的都要返回”调用后的装饰对象“func(*args, **kwargs)
def wrapper1(func):
def inner1(*args, **kwargs):
print('1---start')
res = func(*args, **kwargs)#被装饰对象在调用时,如果还有其他inner,会先执行其他装饰器中的inner
print('1---end')
return res
return inner1
def wrapper2(func):
def inner2(*args, **kwargs):
print('2---start')
res = func(*args, **kwargs)
print('2---end')
return res
return inner2
def wrapper3(func):
def inner3(*args, **kwargs):
print('3---start')
res = func(*args, **kwargs)
print('3---end')
return res
return inner3
@wrapper1 #inner1 = wrapper1(inner2)
@wrapper2 #inner2 = wrapper2(inner3)
@wrapper3 #inner3 = wrapper3(index)
def index():
print('from the index>>>>>')
index()
>>>>>>>>>
1---start
2---start
3---start
from the index>>>>>
3---end
2---end
1---end
装饰器的分类
# 无参装饰器: 装饰在被装饰对象时,没有传参数的装饰器。
'''
# 以下是无参装饰器
@wrapper1 # inner1 = wrapper1(inner2)
@wrapper2 # inner2 = wrapper2(inner3)
@wrapper3
'''
# 有参装饰器: 装饰被装饰的对象时,有传参的装饰器
在某些时候,我们需要给用户的权限进行分类
'''
# 以下是有参装饰器
@wrapper1(参数1) # inner1 = wrapper1(inner2)
@wrapper2(参数2) # inner2 = wrapper2(inner3)
@wrapper3(参数3)
'''
def user_auth(user_role):
'''
有参装饰器函数
'''
def wrapper(func):
def inner(*args, **kwargs):
if user_role == 'vip':
print('welcome!')
res = func(*args, **kwargs)
return res
elif user_role == '普通用户':
print('hi')
res = func(*args, **kwargs)
return res
return inner
return wrapper
@user_auth('普通用户') # wrapper = user_auth('普通用户')--->相当于@wrapper 语法糖
def ndex():
pass
index()
>>>>>>>
hi
wraps 的补充
wraps :是一个修复工具,修复的是被装饰对象的空间
from functools import wraps
def wrapper(func):
def inner(*args, **kwargs):
'''
此处是装饰器的注释
:param func:
:return:
'''
res = func(*args, **kwargs)
return res
return inner # ---》 func
@wrapper
def index():
'''
此处是index函数的注释
:return:
'''
pass
print(index) # 函数对象
# 函数对象.__doc__: 查看函数内部的注释
print(index.__doc__) # inner.__doc__
>>>>>>>
<function wrapper.<locals>.inner at 0x000002A0A52A7C80>
此处是装饰器的注释
:param func:
:return:
下面是使用了wraps后的 修复被装饰对象空间,下面是被装饰对象的注释
def wrapper(func):
@wraps(func) # 修改名称空间: inner ---》 func 此处修改成功
def inner(*args, **kwargs):
'''
此处是装饰器的注释
:param func:
:return:
'''
res = func(*args, **kwargs)
return res
return inner # ---》 func
@wrapper
def index():
'''
此处是index函数的注释
:return:
'''
pass
print(index) # 函数对象
# 函数对象.__doc__: 查看函数内部的注释
print(index.__doc__) # inner.__doc__
>>>>>>>>>>>>
<function index at 0x00000199BCC77C80>
此处是index函数的注释
:return:
编写装饰器 为多个函数加上认证的功能(用户的账号i密码来源于文件)要求登录一次,后续的函数无需再输入用户名和密码。
# 可变类型,无需通过global引用,可直接修改
user_info = {
'user': None # username
}
# 不可变类型,需要在函数内部使用global对其进行修改
user = None
def login():
# 判断用户没有登录时,执行
# 登录功能
# global user
username = input('请输入账号: ').strip()
password = input('请输入密码: ').strip()
with open('user.txt', 'r', encoding='utf-8') as f:
for line in f:
print(line)
name, pwd = line.strip('\n').split(':') # [tank, 123]
if username == name and password == pwd:
print('登录成功!')
user_info['user'] = username
else:
print('登录失败!')
def login_auth(func): # func ---> func1, func2, func3
def inner(*args, **kwargs):
# 已经登录,将被装饰对象直接调用并返回
if user_info.get('user'):
res = func(*args, **kwargs) # func() ---> func1(), func2(), func3v
return res
# 若没登录,执行登录功能
else:
print('请先登录...')
login()
return inner
# func1,2,3 都需要先登录才可以使用,若登录一次,
# 后续功能无需再次登录,绕过登录认证
@login_auth
def func1():
print('from func1')
pass
@login_auth
def func2():
print('from func2')
pass
@login_auth
def func3():
print('from func3')
pass
while True:
func1()
input('延迟操作...')
func2()
func3()
>>>>>>>>>>>>>
请输入你的账户:david
请输入你的密码:123
登录成功
{'user': 'david'}
from func1
延迟操作
from func2
from func3
from func1
延迟操作
# 无参装饰器模板
def wrapper(func):
def inner(*args, **kwargs):
res = func(*args, **kwargs)
# 在被装饰对象调用后添加功能
return res
return inner
# 有参装饰器模板
def outer(arg):
def wrapper(func):
def inner(*args, **kwargs):
res = func(*args, **kwargs)
return res
return inner
return wrapper