Python Enclosing做用域、閉包、裝飾器的基礎篇,請看Python Enclosing做用域、閉包、裝飾器話聊上篇python
Jaglawz: 我常常看到有人的裝飾器是帶參數的,這又是咋回事呢?segmentfault
Pylego: 這個其實很簡單的,你還記得上次我說:緩存
@deco def foo(): pass # 至關於: foo = deco(foo) # 那麼 @new_deco(*args, **kwargs) def bar(): pass # 至關於: bar = new_deco(*args, **kwargs)(bar)
Jaglawz: 也就是說,new_deco返回的是一個裝飾器函數,而後再去裝飾其餘函數。那類裝飾器又是怎麼回事呢?閉包
Pylego: 你知道Python的對象能夠像函數同樣調用嗎?函數
from hashlib import sha256 class HashCache(object): def __init__(self): self.cache = {} def __call__(self, string): if string not in self.cache: self.cache[string] = sha256(string).hexdigest() return self.cache[string] hc = HashCahce() hc('foo') # 像函數同樣調用hc對象 hc('foo') hc('bar')
Jaglawz: 若是是這樣的話我就明白了。code
class FibCache(object): def __init__(self, func): self.func = func self.cache = {} def __call__(self, n): if n not in self.cache: self.cache[n] = self.func(n) return self.cache[n] @FibCache def fib(n): if n == 0: return 0 elif n == 1: return 1 else: return fib(n-1) + fib(n-2) # 至關於: fib = FibCache(fib) # fib(10)至關於FibCache(fib)(10) # 裝飾後的fib是FibCache的一個對象而已 # 也就是說做爲裝飾器的類的構造方法要接收一個待裝飾的函數,而後__call__函數的參數要和待裝飾的函數的參數是同樣的(除了self),這樣的類就能夠用來裝飾函數了
Pylego: 你這個裝飾器厲害,還給fibnacci函數加了緩存,佩服!對象
Jaglawz: 我不會告訴你我是看了大神的傑做而後嚇嚇唬嚇唬你的!ci