What is the purpose of declaring a function within a function?

10

In Python it is possible to declare a function inside another function, as shown in the following code.

def foo(palavra=None):
    print(palavra)
    def bar(outra_palavra=None):
        print(outra_palavra)


if __name__ == '__main__':
    foo(palavra='metodo main')

But what is the practical purpose of such language flexibility? In which scenario do you use such a tool to make a profit?

    
asked by anonymous 05.11.2017 / 07:54

3 answers

14

One reason is encapsulation. If the internal function will be called only by this function does not have to put out. Placing inside ensures that no one else can call.

One thing I notice is that people learn to program without understanding what they are doing and one of the things people do not understand is the function of the function (pun intended :)). Functions serve to abstract algorithms. They serve to indicate with more clarity and organization what you are doing while creating a canonical form of that operation, a concept known as DRY .

It is possible that something that the external function does repeats itself and makes sense to abstract into a function. Since she alone needs this, it is best not to expose her to other parts. The less exposed the less concern you have and the easier it is to maintain.

A cool feature is that you can return the function itself, that is, its method prepares the function and delivery for those who need to use internal. This is done with a technique called anonymous function. So you create a named function and use its name as if it were a variable, so the function is not executed but passed as if it were a die (this is optimized through pointer). Something like this:

def GeraCondicao(valor):
    def Condicao(item):
        return item > valor
    return Condicao

condicao = GeraCondicao(5)
for i in range(0, 10):
    if condicao(i)
        print i

It will print from 6 to 10.

In case I used a closure (#

)

Obviously you can generate this condition in several ways, you can call other functions that create anonymous functions and compose as you need them.

Of course you do not even have to return, you can just move to another function that is calling right there where the built-in function was created.

    
05.11.2017 / 12:07
6

It has some possible uses. The main ones are these two:

factory functions

This may be the primary use. As functions are first class objects in Python, each time a function containing others is called, the internally declared functions are re-created (but not compiled again: the bytecode of nested functions is created in a previous step). They will have access to the external function variables, which will also be separated for each call (which creates a closure).

I think one of the most common uses is when writing a decorator in Python. Decorators in Python are functions that receive as another parameter another function. They return a callable object, usually a function as well, which can execute some code before and after the original function call. So the code for a simple decorator looks like this:

def decorator(func):
    def wrapper(*args, **kwargs):
        # código anterior a chamada original
        ...
        result = func(*args, **kwargs)
        # código posterior a chamada original
        ...
        return result
    return wrapper


@decorator
def minha_funcao():
   ...

In this case, every time "my_function" is called, what will be executed will be the wrapper function declared within decorator - but a wrapper function in which the func variable will be exactly the parameter of the function decorator that receives minha_funcao original as parameter.

If the decorator is used more than once, func will receive the other decorated functions, and a wrapper function will be created for each use.

It is interesting to keep in mind that a nested function can access the variables of the external functions, and in Python 3, to assign new values to these variables, using the nonlocal statement (in Python 2, external variables were read-only).

Readability

Python deliberately restricts "lambda" functions to being just an expression. In general, "lambda" functions are used as parameters for other functions, for example, to obtain the sort key of a string in the sort method, or a command to be executed when a button is clicked from a graphic program .

If the function to be passed as a parameter is a little more complex, and you need to have variables, if s, etc ... it is already worth declaring it as an independent, nested function.

Nothing would prevent it from preventing this nested function from being outside the main code - but the nested declaration allows it to be close to the point where it is used once - and if that logic is related to the outside function.

    
05.11.2017 / 16:04
3

Do not confuse métodos de classe with funções .

It is not possible for a Método de Classe to contain another Método de Classe declared within its scope.

Métodos de Classe are always associated with Classes . They can only be declared within Classe . Métodos de Classe can only be called from the specification of the name of its Classe ( static method ) and / or from an instance of its Classe .

Since função is independent, they can be declared inside other funções as well as within Métodos de Classe . Note that% of% declared within Funções , in fact, Classes !

Allowing Métodos de Classe to be declared within the scope of other funções and / or funções greatly eases Métodos de Classe .

Note that even scripts written in a structured way can encapsulamento their functions, publishing only the functions that really matter to the outsider (the client).

In your example, it reads that: The encapsular function encapsulates the foo() function; It is not interesting that the bar() function is visible by the scope out; The bar() function is closely coupled to the bar() function. No one outside the scope of foo() is able to call foo() .

Encapsulation, if properly applied, greatly increases readability and reuse of code, which in turn greatly facilitates its development and maintenance.

    
05.11.2017 / 17:07