2015-02-24 58 views
0

这会让装饰者感到困惑不解,而装饰工厂需要参数而仍然装饰一个功能何时使用装饰和装饰工厂?

这将有助于何时使用描述。

编辑: 混乱超过一个例子:

def before_run(func): 
    print "hello from before run" 
    def handle_arg(a,b): 
     if(a>0): 
      a= 100 
     return func(a,b) 

    return handle_arg 

@before_run 
def running_func(a,b): 
    print "a",a,"b", b 
    return a+b 

编辑:有没有办法通过添加日志选项(true或false)做到这一点使用装饰的工厂?

+2

你自己已经回答了这个问题。装饰参数的装饰器是装饰器工厂。 – 2015-02-24 10:59:06

+0

@MartijnPieters,但我无法做出完美适合的情况。谢谢 – igaurav 2015-02-24 11:02:02

+0

然后,我不清楚你在这里问什么。 [一些装饰者](https://docs.python.org/2/library/functools.html#functools.wraps)带有参数,而[其他人不会](https://docs.python。组织/ 2 /库/ functions.html#属性)。 – 2015-02-24 11:15:03

回答

3

装饰者工厂只是一个可调用的产生实际的装饰器。它用于使配置装饰器成为可能。

所以不是:

@decorator 
def decorated_function(): 

你会使用:

@decorator_factory(arg1, arg2) 
def decorated_function(): 

和通话将返回实际使用的装饰。

这通常是通过在另一个函数中嵌套装饰器,并使用该新外部函数的参数来调整返回的装饰器的行为来实现的。

为您的样品装饰,缩进你的装饰(你可能想重命名为减少混淆)和一个工厂函数,它的logging参数把它包:

def before_run(logging=True): 
    def decorator(func): 
     print "hello from before run" 
     def handle_arg(a,b): 
      if(a>0): 
       if logging: 
        print "Altering argument a to 100" 
       a = 100 
      return func(a,b) 

     return handle_arg 

    return decorator 

我改名为你的原始before_run()装饰功能以decorator来说明这是工厂生产的装饰器。它在最后返回;这个装饰器功能使用logging作为关闭来打开或关闭日志记录。

1

如果您希望通过参数动态控制装饰器的行为(就像使用任何常规函数一样),您将使用装饰器工厂。例如,假设我想要一个在调用函数之前打印消息的装饰器。我可以这样做:

# Our decorator: 
def print_message_decorator(func): 
    # The wrapper (what we replace our decorated function with): 
    def wrapper(*args, **kwargs): 
     print('A function is being called.') 
     result = func(*args, **kwargs) 
     return result 
    return wrapper 

@print_message_decorator 
def add(a, b): 
    return a + b 

@print_message_decorator 
def subtract(a, b): 
    return a - b 

现在,如果我叫addsubtract每次都会打印A function is being called.

现在说,但是,其实我是想动态生成的装饰,我希望能够自定义每个装饰功能打印输出的信息。我通过将我的装饰器改为装饰器工厂来解决这个问题。

# Our decorator factory: 
def print_message_decorator_factory(msg): 
    # The decorator it creates: 
    def print_message_decorator(func): 
     # The wrapper (what we replace our decorated function with): 
     def wrapper(*args, **kwargs): 
      print(msg) 
      result = func(*args, **kwargs) 
      return result 
     return wrapper 
    return print_message_decorator 

@print_message_decorator_factory('Calling the add function.') 
def add(a, b): 
    return a + b 

@print_message_decorator_factory('Calling the subtract function.') 
def subtract(a, b): 
    return a - b 

现在如果我叫add它打印Calling the add function.,如果我叫subtract它打印Calling the subtract function.