裝飾器本質上就是乙個python函式,他可以讓其他函式在不需要做任何**變動的前提下,增加額外的功能,裝飾器的返回值也是乙個函式物件
裝飾器的應用場景:比如插入日誌,效能測試,事務處理,快取等等場景
現在我有乙個需求,我想讓你測試這個函式的執行時間,在不改變這個函式**的情況下:
importtime
deffunc1():
time.sleep(1)
print('
in func1')
deftimer(func):
definner():
start =time.time()
func()
print(time.time() -start)
return
inner
func1 =timer(func1)
func1()
infunc1
1.0000572204589844
但是如果有多個函式,我都想讓你測試他們的執行時間,你每次是不是都得func1 = timer(func1)?這樣還是有點麻煩,因為這些函式的函式名可能是不相同,有func1,func2,graph,等等,所以更簡單的方法,python給你提供了,那就是語法糖
importtime
deftimer(func):
definner():
start =time.time()
func()
print(time.time() -start)
return
inner
@timer
#==> func1 = timer(func1)
deffunc1():
time.sleep(1)
print('
in func1')
func1()
infunc1
1.0000574588775635
剛剛我們討論的裝飾器都是裝飾不帶引數的函式,現在要裝飾乙個帶引數的函式怎麼辦呢?
importtime
deftimer(func):
definner(name):
start =time.time()
func(name)
print(time.time() -start)
return
inner
@timer
#==> func1 = timer(func1)
deffunc1(name):
time.sleep(1)
print('
我的名字是,
',name)
func1('小紅
')
我的名字是, 小紅1.0000572204589844
importtime
deftimer(func):
def inner(*args,**kwargs):
start =time.time()
func(*args,**kwargs)
print(time.time() -start)
return
inner
@timer
#==> func1 = timer(func1)
deffunc1(name,hooby):
time.sleep(1)
print('
我的名字是 %s,喜歡 %s
' %(name,hooby))
@timer
#==> func1 = timer(func1)
deffunc2(name):
time.sleep(1)
print('
我的名字是 %s
' %(name))
func2('小明
')func1('小紅
','旅遊
')
我的名字是 小明1.0000569820404053我的名字是 小紅,喜歡 旅遊
1.0000574588775635
上面的裝飾器已經非常完美了,但是有我們正常情況下檢視函式資訊的方法在此處都會失效:
defindex():
"""這是乙個主頁資訊
"""print("
from index")
print(index.__doc__) #
檢視函式注釋的方法
print(index.__name__) #
檢視函式名的方法
這是乙個主頁資訊index
如何解決呢?
from functools importwraps
defdeco(func):
@wraps(func)
return func(*args,**kwargs)
return
defindex():
"""哈哈哈
"""print("
from index")
print(index.__doc__)
print(index.__name__)
1、對擴充套件是開放的
為什麼要對擴充套件開放呢?
我們說,任何乙個程式,不可能在設計之初就已經想好了所有的功能並且未來不做任何更新和修改。所以我們必須允許**擴充套件、新增新功能;
2、對修改是封閉的
為什麼要對修改封閉呢?
就像我們剛剛提到的,因為我們寫的乙個函式,很有可能已經交付給其他人使用了,如果這個時候我們對其進行了修改,很有可能影響其他已經在使用該函式的使用者;
裝飾器完美的遵循了這個開放封閉原則;
deftimer(func):
def inner(*args,**kwargs):
'''執行函式之前要做的
'''re = func(*args,**kwargs)
'''執行函式之後要做的
'''return
re
return inner
from functools importwraps
defdeco(func):
@wraps(func)
#加在最內層函式正上方
return func(*args,**kwargs)
假如你有成千上萬個函式使用了乙個裝飾器,現在你想把這些裝飾器都取消掉,你要怎麼做?
乙個乙個的取消掉? 沒日沒夜忙活3天...
過兩天你領導想通了,再讓你加上...
defouter(flag):
deftimer(func):
def inner(*args,**kwargs):
ifflag:
print("
執行函式之前要做的")
re = func(*args,**kwargs)
ifflag:
print("
執行函式後要做的")
return
re
return
inner
return
timer
@outer(true)
#@outer(true) = @timer
deffunc():
print("
1234567890")
func()
執行函式之前要做的1234567890執行函式後要做的
#多個裝飾器裝飾同乙個函式
#有些時候,我們也會用到多個裝飾器裝飾同乙個函式的情況。
def
definner():
print('')
func()
print('')
return
inner
def
definner():
print('')
func()
print('')
return
inner
deff():
print('
test ---------')
f()
Python 基礎 第七天
python3 命名空間和作用域 一般有三種命名空間 內建名稱 全域性名稱 區域性名稱 內建名稱 python 語言內建的名稱,比如函式名 abs char 和異常名稱 baseexception exception 等等 全域性名稱 模組中定義的名稱,記錄了模組的變數,包括函式 類 其它匯入的模組...
python基礎自學 第七天
0.1變數的引用 1.1引用的概念 注意 如果變數已經被定義,當給乙個變數賦值的時候,本質上是修改了資料的引用 1.2函式的引數和返回值的傳遞 呼叫函式時,本質上傳遞的是實參儲存資料的引用 實參的記憶體位址 而不是實參儲存的資料 02.可變和不可變型別 不可變型別,記憶體中資料不允許被修改 數字型別...
python基礎作業第七天
恢復內容開始 1.判斷乙個數是否是水仙花數,水仙花數是乙個三位數,三位數的每一位的三次方的和還等於這個數.那這個數就是乙個水仙花數,例如 153 1 3 5 3 3 3 sum 0 num input 請輸入乙個數字 for c in range len num sum sum int num c ...