Python - 方法出错的多个装饰器

时间:2016-07-13 12:04:29

标签: python python-decorators

我正在尝试学习装饰器,并且在为方法设置多个装饰器时克服了一个奇怪的情况。我有两个装饰器@makeupper@decorator_maker_with_arguments

@decorator_maker_with_arguments演示了如何在装饰器中访问参数。通过打印提供的args可以很好地完成这项工作,但我看到@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

2 个答案:

答案 0 :(得分:1)

  

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

makeupper没有发生故障。外部装饰者decorator_maker_with_arguments未调用wrapper的{​​{1}}。

然后你有一个makeupper,因为你没有从None wrapper返回任何内容。

decorator_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

你可以通过用functool.wraps装饰你的包装来添加一些语法糖,但可以说这是必要的,至少如果你想保留函数名,文档字符串等等。

答案 1 :(得分: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!