在装饰者之前和之后写

时间:2013-09-06 04:54:15

标签: python decorator

我有以下示例代码,

def say_hello(f):
    def wrap():
        print "Hello"
    return wrap

def say_bye(f):
    def wrap():
        print "Bye"
    return wrap

@say_hello
@say_bye
def process():
    return "Processing"

process()

输出:

Hello

我期待输出为:

Bye
Hello
Processing
  1. 可能有什么不对?
  2. 如何在函数调用之前和之后调用那些将被调用的装饰器?
  3. 手段,上面的示例,我可以输出:

        Hello
        Processing
        Bye 
    

3 个答案:

答案 0 :(得分:5)

装饰器返回的“wrap”函数实际上并没有调用它们应该包装的函数。这是一个问题,因为在调用包装函数之前不会调用从装饰器返回的函数。它替换它包装的功能。以下装饰器语法:

@some_decorator
def func(arg):
    function_body()

是以下代码的语法糖:

def func(arg):
    function_body()
func = some_decorator(func)

因此,你想要的是

def say_hello(f):
    def wrap(*args, **kwargs):
        print "Hello"
        return f(*args, **kwargs)
    return wrap

def say_bye(f):
    def wrap(*args, **kwargs):
        return_value = f(*args, **kwargs)
        print "Bye"
        return return_value
    return wrap

@say_hello
@say_bye
def process():
    return "Processing"

这将产生

Hello
Processing
Bye

答案 1 :(得分:3)

你应该在装饰器中调用函数f()。现在要打印第二个装饰器中的值,在执行完函数之后,您可以在打印say_bye之前在该装饰器("Bye")中进行函数调用:

def say_hello(f):
    def wrap():
        print "Hello"
        f()          # call after printing
    return wrap

def say_bye(f):
    def wrap():
        f()          # call before printing
        print "Bye"
    return wrap

@say_hello
@say_bye
def process():
    print "Processing"

process()

<强>输出:

Hello
Processing
Bye

答案 2 :(得分:0)

您的代码与以下代码的工作原理相同:

fun = say_hello(say_bye(process))
fun()

其中say_hello()根本不使用它的参数。