經過咱們的python柯里化就能學習裝飾器啦~!
python
裝飾器應該是目前來講學到的比較困難的,很是很是重要,下面根據代碼演化出裝飾器
ide
需求:
函數
一個加法函數,想加強它的功能,可以輸出被調用過以及調用的參數信息學習
def add(x, y, file): print("call {}, {} + {}".format(add.__name__, x, y), file=file) """" __name__是一個特殊的屬性,將日誌輸出到控制檯 print函數後面其實還能夠跟file,將輸出信息輸出到其它地方,好比d:/123 """ return x + y print(add(4, 5))
上面的加法函數是完成了需求,可是有如下的缺點:
spa
打印語句的耦合過高;日誌
加法函數屬於業務功能,而輸出信息的功能,屬於非業務功能代碼,不應放在業務函數加法中;orm
這種寫法有種稱呼叫作侵入式代碼;it
想一下想要對函數的功能進行加強怎麼辦呢?如何作到業務功能離?io
def add(x, y): return x + y def logger(function): print('-------begin-----')# 加強的輸出 x = function(4, 5)# 至關於x = add(4, 5) print('------end--------')# 加強的功能 return x print(logger(add))
上面代碼作到了業務功能分離,可是x = function(4, 5)這裏會有問題,這裏被寫死了?該如何作呢?
function
def add(x, y): return x + y def logger(function, x, y): print('-------begin-----') x = function(x, y) print('------end--------') return x print(logger(add))
這樣能作到,可是仍是有問題,若是個人函數是這樣寫的,怎麼辦?
def add1(x, y): return x + y def add2(x, y, z): return x + y + z def logger(function, x, y):# x, y這裏寫死確定不行啦 print('-------begin-----') x = function(x, y) print('------end--------') return x print(logger(add1)) print(logger(add2)) ####
怎麼搞定呢?
def add1(x, y): return x + y def add2(x, y, z): return x + y + z def add3(x, y, *args, z): return x + y + z def logger(function, *args, **kwargs): print('-------begin-----') x = function(*args, **kwargs) print('------end--------') return x print(logger(add1, 4, 5)) print(logger(add2, 4, 5, 6)) print(logger(add3, 4, z=5, y=6))
試想還能不能在變化一下?(柯里化)
def add1(x, y): return x + y def add2(x, y, z): return x + y + z def add3(x, y, *args, z): return x + y + z def logger(function): def _logger(*args, **kwargs): print('-------begin-----') x = function(*args, **kwargs) print('------end--------') return x return _logger foo = logger(add1) print(foo(10, 20))
若是把foo = logger(add1)換成add1 = logger(add1),這樣會不會報錯?
不會報錯,那麼就有更簡單的方式了———裝飾器
def logger(function): def _logger(*args, **kwargs): print('-------begin-----') x = function(*args, **kwargs) print('------end--------') return x return _logger @logger # 這句至關於 add1 = logger(add1) def add1(x, y): return x + y print(add1(4, 5))
這就是裝飾器函數.
@logger這句是語法糖,至關於add1 = logger(add1),因此當最後一句print(add1(4,5)),這裏調用的add1至關於調用的是logger函數
的內層函數,跟def add1(x, y)這句沒有關係了
這就是裝飾器的演化,可是前面幾個技術須要熟悉掌握,好比傳參,解構的技巧
注意規範:
外層函數要返回內層函數的引用;
外層函數至少傳入一個參數,這個參數應該是要被包裝的一個函數;
既然是包裝原函數,就不能被改造;