What's the difference including/not including the parentheses on the return
statement for inner function for decorators (and any nested functions)? Are the parenthesis only required if the function returns more than 1 variable?
In the example below I know this won't work unless I use return inner()
, but I see other examples that don't use the ()
on the return
and they work fine.
Terminology behind the reason would great so help me fully understand. Thanks.
def stars(func):
def inner():
print("*" * 50)
func()
print("*" * 50)
return inner()
@stars
def func():
print('Decorate this message.')
It initially prints my message, decorated. But if I call func() again, it will not print anything.
Another working example, but return inner
works fine in this case, long as I have set up my function to support a callable variable, being msg
for my example:
def star(func):
def inner(*args, **kwargs):
print("*" * 30)
func(*args, **kwargs)
print("*" * 30)
return inner
@star
def func(msg):
print(msg)
func("Another message to be decorated")
And I can call func('my new message') each time to print my message, decorated. Why is this compared to the previous example when I don't use a callable function?
In a decorator you should not do return inner()
That would mean you are replacing the decorated func with the result of calling the wrapped func
Your code will immediately print the modified message, without you even trying to call func()
!!
**************************************************
Decorate this message.
**************************************************
But that is not what is intended when you decorate a function.
You intend to modify the behaviour of the function, but you still expect to have to call the function manually.
That is why the code should be:
def stars(func):
def inner():
print("*" * 50)
func()
print("*" * 50)
return inner
@stars
def func():
print('Decorate this message.')
func()
**************************************************
Decorate this message.
**************************************************
To explain further:
When you use the decorator syntax
@stars
def func():
You are telling python to do the following:
func = stars(func)
In other words, def func
but replace the function with the result of calling stars(func)
You might find it less confusing if you don't reuse the name func
in the code. For example:
def stars(func):
def inner():
print("*" * 50)
func()
print("*" * 50)
return inner
@stars
def print_a_message():
print('Decorate this message.')
print_a_message()
**************************************************
Decorate this message.
**************************************************
Maybe it's clearer now that when we do return inner
from the decorator we are telling Python to replace print_a_message
with inner