What is the difference at the time of the return of these two forms?

Asked

Viewed 29 times

-1

def seja_educado(funcao):
    def sendo():
        print('Foi um prazer!')
        funcao()
        print('Tenha um ótimo dia!')
    return sendo

def seja_educado(funcao):
    def sendo():
        print('Foi um prazer!')
        funcao()
        print('Tenha um ótimo dia!')
    return sendo()

What difference does the first function from the second, I mean what difference does it make whether I call the function being or being() ??

  • We can assume that both will be used as decorators, given the "Decorator-Pattern" tag you added to the question?

  • 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

2 answers

2

return sendo() does the following: Python calls the function sendo, rotates your code, and the value it returns is in place of the expression sendo(). In this case, as the function sendo does not have a command return, she returns None and this value is returned by the function seja_educado.

This form does not serve to be a decorator - the function already performs the inner function, and this execution happens only once.

Already in return sendo, the function itself is returned. Think of it as a variable that has the function inside (that’s what function names are in Python) - then, the function return value seja_educado is itself a function - that can be called, whenever you have the () after him - this way serves as a decorator -

When using the syntax of Python decorators - the name of a function with the @ before the declaration of a function, what happens is that the function that is the decorator will be called with the function declared below - and what that function returns will be in place of the function that is decorated. So if a decorator doesn’t return a function, or something else that can be called with "()", the behavior can be very strange.

To better understand, I suggest taking a look at this question that explains nicely decorators:

How Python Decorators Work?

  • The yes now is clearer, thank you very much !

1


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.

  • Very good, thanks for your help !

Browser other questions tagged

You are not signed in. Login or sign up in order to post.