these days, i study python decorator,, and my question code is this.
import functools
def my_decorator(func):
@functools.wraps(func)
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper
@my_decorator
def say_hello():
print("hello!")
ret = my_decorator(say_hello)
ret()
actually, i expect this result
Something is happening before the function is called.
hello!
Something is happening after the function is called.
but real output is like this.
Something is happening before the function is called.
Something is happening before the function is called.
hello!
Something is happening after the function is called.
Something is happening after the function is called.
can someone tell me why result like this?
You have decorated your function say_hello
twice.
Generally, in examples of decorators, the function wrapper is explicitly called i.e:
def outer(f):
def wrapper():
f()
return wrapper
def stuff():
print('hello from stuff')
new_stuff = outer(stuff)
new_stuff()
Which will give 'hello from stuff'
outputted to the console, as new_stuff
is storing the function object wrapper
, returned from outer
. However, using the @decorator
syntactic sugar automatically performs the first call i.e outer(stuff)
. Thus, the example above is comparable to:
def outer(f):
def wrapper():
f()
return wrapper
@outer
def stuff():
print('hello from stuff')
Thus, in your example, simply calling say_hello
(say_hello()
) will correctly output
Something is happening before the function is called.
hello!
Something is happening after the function is called.