- 裝飾器的好處就是在不用更改原函數的代碼前提下給函數增加新的功能
- 兩個原則:
不能修改被裝飾的函數的源代碼
不能修改被裝飾的函數的調用方式
對無參函數進行裝飾
def total_time(func):
def wrapper():
start = datetime.datetime.now()
func()
stop = datetime.datetime.now()
time = (stop - start).seconds
print(time)
return wrapper
@total_time
def pri():
print("計算程序執行時間")
if __name__ == "__main__":
pri()
# #原理:
1.執行函數pri()時,會先調用total_time函數,將被裝飾的函數pri當做入參傳入(此時未pri)
2.在執行total_time函數時,直接把內部函數wrapper返回了,同時把它賦值給pri
3.(重點)此時的pri已經不是未加裝飾時的pri了,而是指向了total_time.wrapper函數地址了
4.接下來,執行新pri函數,即total_time.wrapper函數,先start賦值,然後調用原來的pri(),該處的pri就是通過裝飾傳進來的參數pri
對有參函數進行裝飾
def total_time(func):
def wrapper(*args,**kwargs):
start = datetime.datetime.now()
func(*args,**kwargs)
stop = datetime.datetime.now()
time = (stop - start).seconds
print(time)
return wrapper
@total_time
def pri(a,b,c):
print("計算程序執行時間")
print(a+b+c)
if __name__ == "__main__":
pri(1,2,3)
兩個裝飾器
def makeBold(fun):
print('----a----')
def inner1():
print('----1----')
return '<b>' + fun() + '</b>'
return inner1
def makeItalic(fun):
print('----b----')
def inner2():
print('----2----')
return '<i>' + fun() + '</i>'
return inner2
@makeBold
@makeItalic
def test():
print('----c----')
print('----3----')
return 'hello python decorator'
test()
輸出:
----b----
----a----
----1----
----2----
----c----
----3----
<b><i>hello python decorator</i></b>
原理:
1.在執行@makeBold時,對下面的函數進行裝飾,發現並不是一個函數名,而又是一個裝飾器,@makeBold裝飾器暫停執行,而接着執行接下來的裝飾器@makeItalic
2.把函數test當成參數傳入裝飾器函數makeItalic,打印"b",在makeItalic裝飾完後,此時的test指向makeItalic的inner2函數地址
3.(關鍵)這時會返回來執行@makeBold,接着把新test傳入makeBold裝飾器函數中,因此打印了'a',接着返回inner1,打印“1”
4.(關鍵)然後此時的fun()即是新test,即指向makeItalic的inner2函數地址,打印“2”,此時的inner2中,調用的fun其實才是我們最原生的test函數,打印c,3
5.然後<i>hello python decorator</i>,然後<b><i>hello python decorator</i></b>
參考資料:https://www.jb51.net/article/158814.htm