2014-02-22 80 views
3

我有一個簡單的Python類,我想用它來爲我寫的程序添加命名的鉤子。我嘗試運行下面的代碼,並得到以下輸出。帶參數的Python Decorator類


代碼:

hooks = {} 

class hook(object): 
    def __init__(self, f, hook): 
     if hook not in hooks: 
      hooks[hook] = [] 

     hooks[hook].append({"module": f.__module__, "func": f}) 
     self.f = f 

    def __call__(self, *args): 
     f(*args) 

@hook("test") 
def testHook(): 
    print "hi" 

輸出:

Traceback (most recent call last):      
    File "<stdin>", line 1, in <module>      
TypeError: __init__() takes exactly 3 arguments (2 given) 

我該如何解決這個問題?我使用Python 2.7

回答

6

你的裝飾語法:

@hook("test") 
def testHook(): 
    # ... 

翻譯爲:

def testHook(): 
    # ... 

testHook = hook("test")(testHook) 

所以它只是給出一個參數。你需要重組你的代碼來產生你的類裝飾器返回值hook()

下面將工作:

def hook(hookname): 
    class HookDecorator(object): 
     def __init__(self, f): 
      if hookname not in hooks: 
       hooks[hookname] = [] 

      hooks[hook].append({"module": f.__module__, "func": f}) 
      self.f = f 

     def __call__(self, *args): 
      return self.f(*args) 

    return HookDecorator 

其中__call__使用self.f,而不是全球f,和任何裝飾功能產生的收益。我假設hooks是某個地方的全球字典。

然而,使這個課程沒有多大意義;你使用的狀態很少。你也可以同樣使用包裝功能這裏:

from functools import wraps 

def hook(hookname): 
    def decorator(f): 
     if hookname not in hooks: 
      hooks[hookname] = [] 

     hooks[hookname].append({"module": f.__module__, "func": f}) 

     @wraps(f) 
     def wrapper(*args): 
      return f(*args) 

     return wrapper 

    return decorator 
+0

我明白了。非常感謝! :) –