2016-07-13 30 views
0

我想学习装饰器,并有多个装饰器的方法克服了一个奇怪的条件。我有两个装饰品@makeupper@decorator_maker_with_argumentsPython - 多个装饰器到一个方法出现故障

@decorator_maker_with_arguments演示如何在装饰器中访问参数。这通过打印提供的参数非常好,但我看到@makeupper发生故障。它打印None。我在它的方法定义旁边放了一个print语句,看看它是否被调用并打印出来,但绝不会用hello()大写打印这些字母。

当我评论出@decorator_maker_with_arguments("swadhikar", "c")我看到@makeupper工程很好。有人可以解释我在这里纠结吗?

def makeupper(some_fun):  
    def wrapper(arg1, arg2): 
     return some_fun(arg1, arg2).upper() 
    return wrapper 

def decorator_maker_with_arguments(decorator_arg1, decorator_arg2): 
    """Decorator make that demonstrates decorators with arguments""" 
    print "I am a decorator maker and you passed \"{}:{}\" while calling me...".format(decorator_arg1, decorator_arg2) 

    def my_decorator(fn): 
     def wrapper(fn_arg1, fn_arg2): 
      print "I am the wrapper and I can access the method args \"{}:{}\"".format(fn_arg1, fn_arg2)    
     return wrapper 

    return my_decorator 

@decorator_maker_with_arguments("swadhikar", "c") 
@makeupper 
def hello(ar1, ar2): 
    return "Hello User!" 

结果:

I am a decorator maker and you passed "swadhikar:c" while calling me... 
I am the wrapper and I can access the method args "hello_arg1:another hello arg..." 
None 
+3

你的内包装功能 'decorator_maker ......' 实际上并没有调用函数的装饰 - 这是打算? –

+3

@ TonySuffolk66好 - 它实际上并没有返回任何东西,因此没有'None' ... –

+0

代码行为正确,不清楚为什么你期望打印出'Hello User!''。在应用外部装饰器之后,'fn'(此时实际上来自'makeupper'的'wrapper')不会被调用。 – jonrsharpe

回答

1

但我看到@makeupper故障。它打印None

makeupper没有发生故障。外部装饰器decorator_maker_with_arguments未调用makeupperwrapper

然后你有一个None,因为你没有从wrapperdecorator_maker_with_arguments返回任何东西。

以下修改decorator_maker反映拟议的调整:

def decorator_maker_with_arguments(decorator_arg1, decorator_arg2): 
    """Decorator make that demonstrates decorators with arguments""" 
    print "I am a decorator maker and you passed \"{}:{}\" while calling me...".format(decorator_arg1, decorator_arg2) 
    def my_decorator(fn): 
     def wrapper(fn_arg1, fn_arg2): 
      out = fn(fn_arg1, fn_arg2) 
      print "I am the wrapper and I can access the method args \"{}:{}\"".format(fn_arg1, fn_arg2) 
      return out   
     return wrapper 
    return my_decorator 

输出

I am a decorator maker and you passed "swadhikar:c" while calling me... 
I am the wrapper and I can access the method args "hello_arg1:another hello arg..." 
HELLO USER! 

您可以通过装饰你的包装与functool.wraps添加一些语法糖,但它无疑是必要的,至少如果你想保留的东西像函数名称,文档字符串等

+0

我想你可以说'functool.wraps'是语法糖,但可以说是必要的,至少如果你想保留诸如函数名称,文档字符串等等。 –

+0

@WayneWerner谢谢。 –

1

您可以在my_decorator包装函数中添加return语句。

像以下:

def makeupper(some_fun):  
    def wrapper(arg1, arg2): 
     return some_fun(arg1, arg2).upper() 
    return wrapper 

def decorator_maker_with_arguments(decorator_arg1, decorator_arg2): 
    """Decorator make that demonstrates decorators with arguments""" 
    print "I am a decorator maker and you passed \"{}:{}\" while calling me...".format(decorator_arg1, decorator_arg2) 

    def my_decorator(fn): 
     def wrapper(fn_arg1, fn_arg2): 
      print "I am the wrapper and I can access the method args \"{}:{}\"".format(fn_arg1, fn_arg2)    
      return fn(fn_arg1, fn_arg2) 
     return wrapper 

    return my_decorator 

@decorator_maker_with_arguments("swadhikar", "c") 
@makeupper 
def hello(ar1, ar2): 
    return "Hello User!" 

print hello('arg1', 'arg2') 

输出:

I am a decorator maker and you passed "swadhikar:c" while calling me... 
I am the wrapper and I can access the method args "arg1:arg2" 
HELLO USER! 
相关问题