原理:裝飾器說到底就是閉包的多層運用,內部呼叫外層函式的區域性變數返回給外部函式再在全域性呼叫結果。
原則:1.封閉開放原則。2.把寫的基礎函式(別人或者各個模組呼叫)封閉起來不做更改。3.需要增加功能時,可以拓展。
@語法:加上@符 系統會自動把下面的函式當成引數傳到裝飾器中,從下到上。
功能舉例:假如我們在工作中寫的某個功能,已經在生產線上使用了,然後那些前端工作者呼叫我們的功能函式。但後期需要在原來的基礎上新增新功能而不修改原函式的**,呼叫時還繼續用原函式的名字。
1.裝飾器
比如我們有乙個功能模組是列印出來一句話,但這個功能使用一段時間後客戶在原來的基礎上增加了想顯示執行時間的新需求。我們想了一下,這個簡單,我可以遵守封閉開放原則的同時,把原函式放在乙個新函式裡,這樣就滿足了需求。我們雖然把需求滿足了,但是前端呼叫者不知道我們改函式名了,而且他們也已經習慣原來的呼叫方式。這就用到了裝飾器:
import time
#定義乙個裝飾器
def show_time(f):
def inner():
start_time = time.time() #開始時間
f() #執行原函式
end_time = time.time() #結束時間
print("spend %s"%(end_time-start_time)) #所用時間差
return inner
def foo(): #原函式執行乙個操作
print("fo......")
time.sleep(3) #間停三秒
foo = show_time(foo) #將原函式傳入拓展功能函式 foo = inner
foo() #再呼叫原函式名,從而實現不改函式名再增加新的功能 foo() = inner()
#這次我們運用@語法
@show_time #bar = show_time(bar)
def bar():
print("ba.....")
time.sleep(3)
bar()
2.被裝飾函式的引數
如果被裝飾函式需要傳入不定長引數,那將在裝飾函式中也做出相應的傳參改變。
我們定義乙個加法裝飾器,需要傳入多個引數,然後列印出程式運算的時間。
import time
def show_time(f):
def inner(*args): #傳入功能函式不定長引數
start_time = time.time()
f(*args) #被裝飾函式傳入不定長引數
end_time = time.time()
print("spend %s"%(end_time-start_time))
return inner
@show_time
def add(*args): #給功能函式加不定長引數
sum = 0
for i in args:
sum+=i
print(sum)
time.sleep(1)
add()
3.帶引數的裝飾器
如果我們在用到裝飾器的時候,裡面有個功能,我們想給出訊號就使用,不給訊號不使用。
舉個栗子吧:我們每次用到加法器的時候需要列印一次使用日誌,不使用則不列印。
import time
def logger(flag=''): #列印日誌,預設為空
def show_time(f):
def inner(*args): #傳入功能函式不定長引數
start_time = time.time()
f(*args) #被裝飾函式傳入不定長引數
end_time = time.time()
print("spend %s"%(end_time-start_time))
if flag = 'true': #有對應的引數就呼叫日誌功能
print("列印使用日誌")
return inner
return show_time
@logger('true')
def add(*args): #給功能函式加不定長引數
sum = 0
for i in args:
sum+=i
print(sum)
time.sleep(1)
add()
@logger()
def fo():
print('fo....')
time.sleep(3)
fo()
注意:我們在使用帶有引數的裝飾器的時候,不用擔心最外層函式的影響。它只起到乙個框架的作用,並不影響原來裝飾器的使用,只要注意引數的傳入和內部函式接收到引數時做判斷後給出的動作,也可以有多個不同動作,這個看個人需求。 Python 裝飾器例項
偶然看到一篇文章,想到了前幾天的乙個需求,git pull效能不穩,需要加入重試機制,正好這個裝飾器的例項符合這樣的場景。coding utf 8 import time import logging import socket from functools import wraps logging...
python裝飾器及簡單例項
裝飾器 加入購物車,付款,修改收穫位址 判斷使用者登入狀態 def func number a 100 def inner func nonlocal a nonlocal number number 1 for i in range number a 1 print 修改後的a的值 a retur...
Python之裝飾器的例項
1.1裝飾器的應用 引數型別檢查 函式引數的檢查,一定是在函式外 函式應該作為引數,傳入到檢查函式中 檢查函式拿到函式傳入的實際引數,與形參宣告對比 annotations 屬性是乙個字典,其中包括返回值型別的宣告。假設要做位置引數的判斷,無法和字典中的宣告對應。使用inspect模組 inspec...