一、引出裝飾器概念
引入問題: 定義了一個函數,想在運行時動態的增加功能,又不想改動函數本身的代碼?
示例:
希望對下列函數調用增加log功能,打印出函數調用:
def f1(x): return x*2 def f2(x): return x*x def f3(x): return x*x*x
方法一:直接修改原函數的定義
def f1(x): print 'call f1()' return x*2 def f2(x): print 'call f2()' return x*x def f3(x): print 'call f3()' return x*x*x
思考:高階函數
(1)、可以接受函數作為參數
(2)、可以返回函數
(3)、那么可否通過接收一個函數,內部對其包裝,然后返回一個新函數,這樣子動態的增強函數功能
方法二:通過高階函數返回新函數
def f1(x): return x*2
def new_fn(f):
'''裝飾器函數'''
def fn(x):
print 'call' + f.__name__ + '()'
return f(x)
return fn
g1 = new_fn(f1)
print g1(5)
輸出結果:
通過高階函數達到我們的目的。
但是我們修改程序如下:
def f1(x): return x*2
def new_fn(f):
'''裝飾器函數'''
def fn(x):
print 'call' + f.__name__ + '()'
return f(x)
return fn
f1 = new_fn(f1)
print f1(5)
輸出結果:
是一樣的。但是這樣子的話,f1的原始定義函數就被徹底隱藏了。
二、裝飾器概念
(1)、python內置的 @ 語法就是為了簡化裝飾器的使用。
進行裝飾器的修飾之后:
下面的代碼一和代碼二在python中是等價的。
代碼一: @new_fn def f1(x): return x*2 print f1(5) 代碼二: def f1(x): return x*2 f1 = new_fn(f1) print f1(5)
輸出結果:
是一樣的。
裝飾器可以這么理解:通過高階函數傳遞函數參數,新函數添加舊函數的需求,然后執行舊函數。
三、裝飾器作用:
可以極大簡化代碼,避免每個函數編寫重復性的代碼
(1)、打印日志:@log (2)、檢測性能:@performance
(3)、數據庫事務:@transaction (4)、URL路由:@post(’/register’)
四、裝飾器函數三步走
(1)定義自己先要執行的函數
(2)
def new_fn(要執行的函數名字):
def fn(要執行的參數函數參數/或者沒有參數):
添加要添加的函數功能
return f(x) 函數的執行結果
return fn
(3)裝飾器進行修飾
轉載自:https://blog.csdn.net/li_101357/article/details/52749449
