def fibonacci(n): if n in (0, 1): return n return fibonacci(n-1) + fibonacci(n-2)定義下面的 decorator
class memoized(object): def __init__(self, func): self.func = func self.cache = {} def __call__(self, *args): try: return self.cache[args] except KeyError: self.cache[args] = value = self.func(*args) return value
使用方法很簡單在函式定義上一行加上
@memoized
即可,之後呼叫 fibonacci(n) 時,
程式會先檢查快取中有沒有這個值,如果有就傳回,
如果沒有就呼叫 fibonacci(n),之後把計算得到值存入快取,再傳回。
之後如果我們想要替任何一個函式加上快取,只要在函式定義上一行加上
@memoized
,而不需要更動函式實作,是不是很方便呢?
def compute(x): return x**3 - 1此函式的輸入是一個數字,如果輸入想改成數字串列的話, 一般的想法是直接更改函式實作,可是如果有很多類似函式, 一個一個改就嫌累贅,這時 decorator 就派上用場了,定義
def elementwise(fn): def newfn(arg): if hasattr(arg,'__getitem__'): # is a sequence return type(arg)(map(fn, arg)) else: return fn(arg) return newfn
在 compute() 定義上一行加上 @elementwise
,
函式就可以接受數字串列了。
之後呼叫 compute(x) 時,函式會判斷輸入變數是不是串列,
如果不是的話,就直接傳回 compute(x),如果是的話,
會產生一個新的串列,其元素是 compute(y),y 是 x 其中一個元素。
(如果對 map 不熟的話,可以參考
之前的部落格,其實不用 map,改用 list comprehension 也可以。)
由於 map 的傳回值型態是 list,為了讓傳回值型態跟輸入型態一致,
所以 map 前要加上 type(arg)
轉型。
註: 第一個例子來自 Python Decorator Library 的第三個範例,而第二個例子來自 Charming Python 的 Listing 12。
No comments:
Post a Comment