-
裝飾器的應(yīng)用場景:
面向?qū)ο?OOP)
登錄認(rèn)證
flask路由,全部都是有參裝飾器
裝飾器:在不修改源代碼及調(diào)用方式的前提下,額外添加新的功能,符合開放封閉封閉原則就是裝飾器:
對額外新增的功能是開放的
對源代碼及調(diào)用方式是封閉的
# 3個人寫的代碼,分別計算各自代碼運行的時間,但是又不能改變代源代碼
import time
?
# 創(chuàng)建一個裝飾器函數(shù)
def run_time(f):
'''
計算時間的函數(shù)
:param f: 接收要計算時間的函數(shù)
'''
def inner();
start_time = time.time()
f()
time.sleep(2)
end_time = time.time()
print(f'{f}運行時間:{end_time-start_time}')
return inner
?
def func():
print('這是jones寫的代碼')
def foo():
print('這是tins寫的代碼')
def fl():
print('這是zhong寫的代碼')
a = func # a就是func函數(shù)
func = run_time # func就是run_time
func(a) # 本質(zhì)上還是run_time(func),但是不滿足調(diào)用方式方式封閉
func()
標(biāo)準(zhǔn)版裝飾器實現(xiàn)原理:
- 類似于現(xiàn)實中的租房,裝飾器就是中介.通過中介來交易
def wrapper(func):
def inner(*args,**kwargs):
# 執(zhí)行被裝飾的函數(shù)前
func(*args,**kwargs)
# 執(zhí)行被裝飾的函數(shù)后
return inner
?
def func1():
print('這是jones寫的代碼')
func = wrapper(func1)
func()
- 類似于淘寶的案例
def tb(func):
def inner(*args,**kwargs):
res = func(*args,**kwargs)
return res
return inner
?
@tb # 語法糖 store=tb(store)
def store(money):
'''
賣家
'''
print(f'xx名{money}元賣了一個皮包')
return 'lv'
?
print(store(100)) # 買家花了100
帶參數(shù)的裝飾器:
# arg只是需要滿足執(zhí)行的條件,才能往下執(zhí)行裝飾器
def f(a):
def auth(arg):
def wrapper(func):
def inner(*args,**kwargs):
if arg:
print('開始裝飾')
ret = func(*args,**kwargs)
print('裝飾成功!')
else:
ret = func(*args,**kwargs)
return ret
return inner
return wrapper
return f
auth = f(1)
@auth(1) # 本質(zhì)上就是foo = auth(True)(foo)
def func(a):
print(a)
func(10)
=無論有多少個嵌套函數(shù),都是一樣的,一層一層解開即可=

image-20200919180422289.png
多個裝飾器裝飾一個函數(shù)
def wrapper(func):
def inner(*args, **kwargs):
print('is wrapper start')
ret = func(*args, **kwargs)
print('finish wrapper')
return ret
return inner
def wrapper1(func):
def inner1(*args, **kwargs):
print('is wrapper start')
ret1 = func(*args, **kwargs)
print('finish wrapper')
return ret1
return inner1
# 拆語法糖執(zhí)行順序
@wrapper # 1.foo = wrapper(foo)
@wrapper1 # 2.foo = wrapper1(foo)
def foo():
print('is foo')
foo() # 3.foo() = inner1()
# 4.foo() = inner()
-----------------------------------------
is wrapper start
is wrapper1 start
is foo
finish wrapper1
finish wrapper
- 多個裝飾器的執(zhí)行順序是
- 程序是從上往下執(zhí)行的,所以先解開的語法糖是
wrapper,再解開wrapper2,所以輸出的是is wrapper start,在輸出is wrapper1 start - 然而此時的
foo() == inner1(),因為只調(diào)用了一次foo()所以,往下執(zhí)行的是finish wrapper1 - 到這wrapper1已經(jīng)執(zhí)行完了,而wrapper還沒有執(zhí)行完,所以接著執(zhí)行
finish wrapper整個程序執(zhí)行結(jié)束
image.png
