2012-04-12 44 views
3

最近在Python裝飾器上閱讀這個article,它舉例說明了memoization作爲Python裝飾器應用的技術。雖然我對Python裝飾器有一個很好的理解,但我希望知道裝飾器的更多有效用例,以及您如何在日常代碼中使用它們。Python裝飾器的典型應用和使用案例

+0

的[什麼是memoization的好,是不是真的那麼有用嗎?]可能重複(http://stackoverflow.com/questions/3242597/what-is-memoization-good-for-and-is - 真的,所有有用的) – detly 2012-04-12 12:19:13

+0

我意識到重複不是特定於Python的,但我認爲它會回答你的問題。 – detly 2012-04-12 12:21:25

+1

@detly其實不,我的問題根本不是關於記憶,我只是想用一個例子來說明。我的問題具體是關於python裝飾器和它們的好用例如備忘錄 – subiet 2012-04-12 12:24:10

回答

0

您可以查看Django Web框架中的Python裝飾器的有效用例authdocs。清晰的例子(我每天親自使用)包括restricting views to authenticated users,restricting access depending on specific user permissions等的裝飾器的使用。

+1

爲了便於他人@Josvic的回答可能指的是[this](https://docs.djangoproject.com/en/dev/topics/http/decorators/)等等。 – subiet 2012-04-12 12:19:40

+0

@subiet確實如此。我只是提到具體的,我真的覺得有用:) – 2012-04-12 12:20:59

+0

感謝您編輯答案:) – subiet 2012-04-12 12:22:53

0

這是一個實際的例子。看看斐波那契的系列總和和沒有備忘錄。

from functools import wraps 
def memo(func): 
    cache = {} 
    @wraps(func) 
    def wrap(*args): 
     if args not in cache: 
      cache[args] = func(*args) 
     return cache[args] 
    return wrap 

def fib(i): 
    if i < 2: return 1 
    return fib(i-1) + fib(i-2) 

@memo 
def fib_memo(i): 
    if i < 2: return 1 
    return fib_memo(i-1) + fib_memo(i-2) 

現在測試速度差!

>>> print fib(200) 
... 
>>> print fib_memo(200) 
... 
+0

這是我在問題的鏈接中提到的確切例子。在這種情況下裝飾器的用處促使我尋求像這樣的進一步用例:) – subiet 2012-04-12 12:21:10

+0

@subiet我沒有閱讀文章,經典的例子,它幾乎看起來像一個精確的複製粘貼:)。無論如何,當你使用算法時,節點和圖形備忘錄用於消除所謂的遞歸複雜性(在分區和搜索中尤其有用)。 – luke14free 2012-04-12 12:24:28

2

有一些內置的裝飾,可以是有用的,如classmethodpropertystaticmethod,並functools.wrap的。編寫一個裝飾器來記錄函數的使用情況以便進行調試通常很方便。 this Python wiki page上有很多示例裝飾器,但我認爲其中至少有一些更多的目的是展示Python的靈活性,而不是實際提供有用的功能。

1

由於Python 3支持類型註釋,因此可以使用裝飾器作爲檢查方法。

def check(f): 
    def _f(x): 
     if type(x) != f.__annotations__['x']: 
      raise TypeError(type(x)) 
     val = f(x) 
     if 'return' in f.__annotations__ and f.__annotations__['return'] != type(val): 
      raise TypeError(type(val)) 
     return val 
    return _f 

@check 
def f(x: int) -> int: 
    return x * 2 

>>> f(2) 
4 

>>> f('x') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 4, in _f 
TypeError: <class 'str'>