2014-03-27 69 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)装修。有时很有用。