装饰器之起飞版
原则:
装饰器去装饰一个函数 :不改变被装饰函数的源代码,不改变被装饰函数的调用方式
# 基础形态 **********这才是终极版************
def wrapper(func): # func函数对象 ---> 被装饰对象 # *args, **kwargs用于接收被装饰对象的参数 def inner(*args, **kwargs): # 在调用被装饰对象前 添加新功能 @beforemethod res = func(*args, **kwargs) # 被装饰函数 # 在调用被装饰对象后 添加新功能 @aftermethod return res return inner def sleep(): print('111') sleep = wrapper(sleep) # = return inner 即sleep = inner = @wrapper sleep() =inner() # sleep() = 装饰器里面的inner() , #可以debug看一下
#也可以写成
@wrapper
sleep()
总结:1.被装饰装饰过的函数:调用被装饰函数时 就是在调用装饰器里面的inner()
2. 可以在被装饰对象前加新功能,也可以在被装饰函数后面加新功能
3.不改变被装饰函数的调用方式:1.不改变原函数名 2.不改变被调用函数的参数
4. 如果装饰中没有增加任何新功能只有被装饰的函数,这里叫作空装饰器,调用被空装饰其装饰的函数时,相当于直接执行被装饰的函数
5. 当装饰器中没有被装饰的函数res = func(*args,**kwargs) 时,只会执行装饰器中的代码,不会再调用被装饰的函数
def wrapper1(func): def inner1(*args, **kwargs): print('1---start') # 被裝飾對象在調用時,如果還有其他裝飾器,會先執行其他裝飾器中的inner # inner2 # res = func(*args, **kwargs) 被装饰函数 print('1---end') # return res return inner1 @wrapper1 # index《---inner1 = wrapper1(inner2) # @wrapper2 # inner2 = wrapper2(inner3) # @wrapper3 # inner3 = wrapper3(index) def index(): # 被裝飾對象 # inner1 ---》 print('from index...') index() 1---start from index... 1---end
2.叠加装饰器
def wrapper1(func): def inner1(*args, **kwargs): print('1---start') # 被裝飾對象在調用時,如果還有其他裝飾器,會先執行其他裝飾器中的inner # inner2 res = func(*args, **kwargs) 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 ''' 叠加裝飾器的裝飾順序與執行順序: - 裝飾順序: 调用wrapper装饰器拿到返回值inner 由下往上裝飾 - 執行順序: 调用装饰过后的返回值inner 由上往下執行 ''' @wrapper1 # index《---inner1 = wrapper1(inner2) @wrapper2 # inner2 = wrapper2(inner3) @wrapper3 # inner3 = wrapper3(index) def index(): # 被裝飾對象 # inner1 ---》 print('from index...')
index()
>>> 1---start
>>> 2---start
>>> 3---start
>>> from index...
>>> 3---end
>>> 2---end
>>> 1---end
总结:从下往上装饰,从上往下执行,一层包一层
3.有参装饰器 @user_auth('svip') 加一层函数传参去判断 用户类型
# 有参装饰器 def user_auth(user_role): # 'SVIP' def wrapper(func): def inner(*args, **kwargs): if user_role == 'SVIP':
print('前超级用户') # 添加超级用户的功能 res = func(*args, **kwargs)
print('后超级用户') return res elif user_role == '普通用户': print('普通用户') # 添加普通用户的功能 res = func(*args, **kwargs) return res return inner return wrapper # 被装饰对象 # @user_auth('SVIP') wrapper = user_auth('普通用户') # @user_auth('SVIP') # wrapper = user_auth('普通用户') def index(): print('被装饰函数') index()
>>> 前超级用户
>>> 被装饰函数
>>> 后超级用户