English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Manual de Referência do Python
Variáveis não locais em funções aninhadas
Uma função definida dentro de outra função é chamada de função aninhada. A função aninhada pode acessar variáveis do escopo encerrado.
No Python, por padrão, essas variáveis não locais são apenas leitura e devemos declará-las explicitamente como não locais (usandoPalavra-chave nonlocal)para poder modificá-lo.
Aqui está um exemplo de função aninhada que acessa variáveis não locais.
def print_msg(msg): # Isso é a função externa de encerramento def printer(): # Isso é uma função aninhada print(msg) printer() # Executamos essa função # Saída: Hello print_msg("Hello")
Podemos ver que a função aninhada printer() pode acessar variáveis não locais do escopo encerradomsg.
O que acontece se a última linha da função print_msg() retornar a função printer() em vez de chamá-la? Isso significa que a definição da função é como follows.
def print_msg(msg): # Isso é a função externa de encerramento def printer(): # Isso é uma função aninhada print(msg) return printer # Isso mudou # Agora, vamos tentar chamar essa função. # Saída: Hello another = print_msg("Hello") another()
Isso é pouco comum.
A função print_msg() chamada com uma string, "Hello", retorna a função ligada aOutroNome. Ao chamar another(), apesar de termos concluído a execução da função print_msg(), ainda lembramos dessa mensagem.
Essa técnica de adicionar alguns dados ("Hello") ao códigoem PythonchamadoEncerramento.
Mesmo se a variável estiver fora de escopo ou a função já tiver sido removida do espaço de nomes atual, ela lembrará desse valor no escopo encerrado.
Tente executar o seguinte comando no Python Shell para ver a saída.
>>> del print_msg >>> another() Hello >>> print_msg("Hello") Traceback (most recent call last): ... NameError: name 'print_msg' is not defined
From the above example, we can see that in Python, when a nested function refers to a value in its enclosed scope, we have a closure.
The following points summarize the conditions that must be met to create a closure in Python.
We must have a nested function (function inside a function).
The nested function must refer to values defined in the enclosed function.
The enclosed function must return an nested function.
So, what is the use of closure?
Closure can avoid using global values and provide some form of data hiding. It can also provide an object-oriented solution to the problem.
When there are few methods implemented in a class (most of the time it is one method), closure can provide another more elegant solution. However, when the number of properties and methods increases, it is best to implement a class.
This is a simple example where closure may be more preferable than defining a class and creating an object.
def make_multiplier_of(n): def multiplier(x): return x * n return multiplier # 3multiplier times3 = make_multiplier_of(3) # 5multiplier times5 = make_multiplier_of(5) # Output: 27 print(times3(9)) # Output: 15 print(times5(3)) # Output: 30 print(times5(times3(2))
Python decorators alsoA lot of closures are used.
Finally, it is best to point out that you can find the values enclosed in the closure function.
All function objects have a __closure__ attribute, if it is a closure function, then this attribute returns a tuple of cell objects. Refer to the example above, we know that times3and times5It is a closure function.
>>> make_multiplier_of.__closure__ >>> times3__closure__ (<cell at 0x0000000002D155B8: int object at 0x000000001E39B6E0>,)
The cell object has an attribute cell_contents that stores closed values.
>>> times3__closure__[0].cell_contents 3 >>> times5__closure__[0].cell_contents 5