關於裝飾器咱們先來了解了解什麼是閉包閉包
0X01app
閉包概念函數
closure:內部函數中對enclosing做用域的變量進行引用spa
0X02指針
看段小Democode
def func(val):def in_func(): print (val) in_func() return in_func f = func(89) f()
咱們首先能夠看到在func函數中定義了一個函數in_func,那麼調用func函數返回in_func函數。對象
從C語言角度講就是返回了一個函數指針,但是咱們看看運行結果blog
89 89
f()函數的返回結果是89作用域
func函數調用完成從C語言來角度來講調用棧清除,爲何f()函數還能89呢?class
0X03
首先咱們應該瞭解的是在Python中與C不一樣的是Python函數是一種對象!
那麼看看val與函數f()的地址
def func(val): print ('%x'%id(val)) def in_func(): print (val) in_func() return in_func f = func(89) f() print (f.__closure__)
運行結果以下
2ff8598 89 89 (<cell at 0x03025650: int object at 0x02FF8598>,)
咱們發現地址都是0X02FF8598!
那麼閉包實際就是內置函數把引用的變量放入了本身函數屬性中進行返回
0X04
既然值能夠做爲函數屬性與函數一塊兒返回,那麼函數也能夠做爲另函數屬性返回
def dec(func): def in_dec(*arg): print 'In dec' if len(arg) == 0: return 0 for val in arg: if not isinstance(val, int): return 0 return func(*arg) return in_dec def my_sum(*arg): return sum(arg) my_sum = dec(my_sum) print my_sum(1,2,3,4,5,6)
如上所示,其實裝飾器也就是閉包的一種。
綜上所述
1.裝飾器用來裝飾函數
2.返回一個函數對象
3.被裝飾函數標識符指向返回的函數對象
0X05
無參數裝飾器
def dec(func): def in_dec(*arg): print 'In dec' if len(arg) == 0: return 0 for val in arg: if not isinstance(val, int): return 0 return func(*arg) return in_dec @dec #my_sum = dec(my_sum) def my_sum(*arg): return sum(arg) print my_sum(1,2,3,4,5,6)
對照上個閉包來看@dec的做用就是 執行了my_sum = dec
0X06
有參數裝飾器
有參數裝飾器相對於無參數裝飾器來講就至關於多了一層嵌套
def log(prefix): def log_decorator(f): def wrapper(*args, **kw): print '[%s] %s()...' % (prefix, f.__name__) return f(*args, **kw) return wrapper return log_decorator @log('DEBUG') def test(): pass print test()
咱們把@log('DEBUG')進行展開
my_func = log('DEBUG')(my_func)
上面的語句看上去仍是比較繞,再展開一下:
log_decorator = log('DEBUG') my_func = log_decorator(my_func)
上面的語句又至關於:
log_decorator = log('DEBUG') @log_decorator def my_func(): pass
本質上就是多返回了一層裝飾器而已