Just make a simple table test. Assuming there is any function called spam
, we can analyze both implementations.
def spam():
""" Uma função qualquer """
...
In the first form we have:
def seja_educado(funcao):
def sendo():
print('Foi um prazer!')
funcao()
print('Tenha um ótimo dia!')
return sendo
That is, we define a function seja_educado
which takes a function as a parameter; we define a new function locally sendo
which will perform the input function with the messages before and after; the function seja_educado
returns the function sendo
. That is, the return of the function seja_educado
is a function. So we can test it:
>>> egg = seja_educado(spam)
>>> type(egg)
<function seja_educado.<locals>.sendo at 0x...>
Thus, being egg
a function, we can call it, egg()
, and this will perform the function sendo
, that will display the message "It was a pleasure!", will perform the function spam
, which is what we pass as parameter when defining egg
and finally display the message "Have a great day!"
Already in the second form we have:
def seja_educado(funcao):
def sendo():
print('Foi um prazer!')
funcao()
print('Tenha um ótimo dia!')
return sendo()
The implementation is basically the same as the first form, only differentiating in the return type. While the first returns the function sendo
this form will return the function return sendo
. However, the local function sendo
does not have explicit feedback and therefore will be None
. Thus, the return of the function seja_educado
will always be None
.
Doing the same as we did in the first form, we will have:
>>> egg = seja_educado(spam)
Foi um prazer!
Tenha um ótimo dia!
>>> type(egg)
None
That is, the function spam
will already be executed at the time seja_educado
call and return in egg
will always be None
.
In the field of decorators, the first makes more sense, because the return is a function - the second can make sense, in very specific situations, because by using a decorator in a function you will overwrite it with the return of this decorator. That is, to do:
@seja_educado
def spam():
...
It’s the same as doing:
def spam():
...
spam = seja_educado(spam)
In the second way, as the return is always None
, when using as a decorator you would be setting spam
as None
, which makes no sense in the vast majority of cases.
We can assume that both will be used as decorators, given the "Decorator-Pattern" tag you added to the question?
– Woss
It is that I am studying about Decorators in Python and there in one of the videos the teacher explained only that it was not very clear about the call of this function of these two modes
– Pedro_Aquino