如何在python decorator

时间:2016-09-21 10:44:37

标签: python

最近我正在学习Python装饰器并使用functools.wraps

def a():
    def b():
        def c():
            print('hello')
        return c
    return b


print a.__name__
#output:a

我理解为什么输出是a。但我不知道__name__在以下代码中的变化。

def log(text):
    def decorator(func):
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kw)
        return wrapper
    return decorator

@log('...')
def simple():
    print('*' * 20)

print simple.__name__
#output:wrapper

为什么输出是'wrapper'而不是'decorator'或'log'?

3 个答案:

答案 0 :(得分:2)

一些基础知识:

@decorator
def f():
    pass

相当于:

def f():
    pass
f = decorator(f)

带args的装饰者:

@decorator(*args, **kwargs)
def f():
    pass

相当于:

def f():
    pass
decorator_instance = decorator(*args, **kwargs)
f = decorator_instance(f)

知道了,我们可能会将您的示例重写为:

def simple():
    print('*' * 20)

log_instance = log('...')
simple = log_instance(simple)

让我们分析最后两行中发生的事情:

  • log_instance是一个decorator函数,其中的文本变量等于' ...'
  • 由于decorator(无论text值如何)返回名为wrapper的函数,simple将替换为名为wrapper的函数

答案 1 :(得分:0)

当使用该函数/类作为参数调用时,装饰器的意思是用函数或类替换装饰器返回的内容。带参数的装饰器有点复杂,因为你首先调用外部方法(log)来获得“参数化”装饰器(decorator),然后你调用那个并获得最终函数({ {1}}),它将替换修饰函数(wrapper)。

所以,给它一些结构,

  1. simple为参数调用log并获取'...'
  2. decorator为参数调用decorator并获取simple
  3. wrapper替换为simple

答案 2 :(得分:0)

@log('...')
def simple(...

相当于

def simple(...
simple = log('...')(simple)

所以实际调用log,返回decorator,用simple作为参数调用,然后用decorator的返回值替换,这是函数wrapper,因此其__name__wrapper