2014-03-27 61 views
2

是否有可能將修飾方法參數傳遞給修飾器的__init__將參數傳遞給裝飾器?

一個簡單的裝飾和使用例

class Decorator(object): 
    def __init__(self, *args): 
     print args 

    def __call__(self, func): # yep the method still have to be callable 
     return func 

@Decorator 
def foo(): 
    pass 

沒有參數裝飾器將通過該方法作爲參數

$ python foo.py 
(<function foo at 0x7fefd7ac1b90>,) 

當我添加參數給裝飾

@Decorator(1, 2, 3) 
def foo(): 
    pass 

它結果lts in

$ python test.py 
(1, 2, 3) 

正如您所看到的,現在在傳遞的參數中缺少方法。

+0

用'@Decorator()'嘗試一個例子,也許它會點擊。 –

+2

有一個很好的描述[這裏](http://stackoverflow.com/a/1594484/674039)(堆棧中的最佳答案之一,在我看來) – wim

+1

'@ Decorator'基本上是指'foo = Decorator(foo )'。因此'@Decorator(1,2,3)'意味着'foo = Decorator(1,2,3)(foo)'; 'Decorator(1,2,3)'應該返回一個裝飾器*。 – RemcoGerlich

回答

4

當我們將參數傳遞給我們需要創建接受那些參數,並然後附加功能的裝飾返回實際的裝飾:

def decorator_creator(*args): 
    class Decorator(object): 
     def __init__(self, func): 
      print args 
      print func 
      self.func = func 
     def __call__(self): 
      return self.func() 
    return Decorator 

@decorator_creator(1, 2, 3) 
def foo(): 
    pass 

輸出:

(1, 2, 3) 
<function foo at 0x0000000002EB9EB8> 
+1

值得注意的是,對絕大多數情況來說,實現一個裝飾器作爲一個類,即使它需要參數,也是過度的,並且可以說是不那麼明確的代碼;外部關閉通常就足夠了,並且可以獲得更多可讀代碼。或者至少在裝飾器函數作用域外定義裝飾器對象,然後在調用裝飾器時初始化並返回一個實例。 –

+0

只是一個小小的觀察,每次應用裝飾器時,此代碼是否不會創建一個'Decorator'類? –

+0

@PauloBu這是必需的,因爲我們在這裏使用了一個自由變量'args'。如果我們將這個類移出函數外,那麼這個類將不能訪問'args'。 –

2

一個,它沒有按「替代t需要內部類:

class decorator(object): 
    def __init__(self, *args): 
     # This creates the decorator 
     self.args = args 

    def __call__(self, func): 
     # This applies the decorator 
     self.func = func 
     return self.call 

    def call(self, *moreargs): 
     # And this happens when the original function is called 
     print self.args, self.func, moreargs 
     return self.func() 

@decorator(1, 2, 3) 
def foo(): 
    pass 

我也使用了functools.partial(self.method, func)裝修。有時很有用。