简体   繁体   中英

Write before and after decorator

I have following sample code,

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()

Output:

Hello

I was expecting output as:

Bye
Hello
Processing
  1. What could be wrong?
  2. How to make decorators those will be called before and after function call?

Means, with above example, Can I have output:

    Hello
    Processing
    Bye 

The "wrap" functions returned from your decorators don't actually call the function they were supposed to be wrapping. This is a problem, because the function returned from a decorator isn't called before the wrapped function is called; it replaces the function it's wrapping. The following decorator syntax:

@some_decorator
def func(arg):
    function_body()

is syntactical sugar for the following code:

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

Thus, what you want is

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"

This will produce

Hello
Processing
Bye

You should call the function f() inside the decorators. Now to print the value in 2nd decorator, after your after your function executes, you can just make the function call in that decorator ( say_bye ) before printing "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()

Output:

Hello
Processing
Bye

Your code works the same as the following code:

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

where say_hello() doesn't use it's parameter at all.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM