English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Tutoriales básicos de Python

Control de flujo de Python

Funciones en Python

Tipos de datos en Python

Operaciones de archivos de Python

Objetos y Clases de Python

Fecha y Hora de Python

Conocimientos Avanzados de Python

Manual de Referencia de Python

Closures en Python

En este artículo, usted aprenderá qué es un cierre en Python, cómo definir un cierre y las razones para usar un cierre.

Variable no local en una función anidada

Antes de entender qué es un cierre, debemos entender primero qué es una función anidada y una variable no local.

Una función definida dentro de otra función se llama función anidada. La función anidada puede acceder a las variables del ámbito cerrado.

En Python, por defecto, estas variables no locales son de solo lectura y debemos declararlas explícitamente como no locales (usandopalabra clave nonlocal)para poder modificarlos.

A continuación se muestra un ejemplo de una función anidada que accede a variables no locales.

def print_msg(msg):
# Esto es una función cerrada externa
    def printer():
# Esto es una función anidada
        print(msg)
    printer()
# Ejecutamos esta función
# Salida: Hola
print_msg("Hola")

Podemos ver que la función anidada printer() puede acceder a las variables no locales del ámbito cerradomsg.

Definir la función de cierre

¿Qué sucederá si la última línea de la función print_msg() devuelve la función printer() en lugar de llamarla? Esto significa que la definición de la función es como sigue.

def print_msg(msg):
# Esto es una función cerrada externa
    def printer():
# Esto es una función anidada
        print(msg)
    return printer # Esto ha cambiado
# Ahora, intentemos llamar a esta función.
# Salida: Hola
another = print_msg("Hola")
another()

esto es inusual.

La función print_msg() se llama con una cadena, el "Hola" devuelto por la función se une aotroNombre. Al llamar a another(), aunque ya hemos completado la ejecución de la función print_msg(), aún recuerda este mensaje.

Esta es una técnica que adjunta algunos datos ("Hola") a un códigoen PythonllamadoCierre.

Incluso si la variable está fuera de rango o la función se ha eliminado del espacio de nombres actual, se recuerda este valor en el ámbito cerrado.

Intente ejecutar el siguiente comando en el Shell de Python para ver la salida.

>>> del print_msg
>>> another()
Hola
>>> print_msg("Hola")
Traceback (llamada más reciente):
...
Error de nombre: nombre 'print_msg' no definido

What are the conditions for closure?

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 closure in Python.

  • We must have a nested function (function inside a function).

  • The nested function must refer to the values defined in the enclosed function.

  • The enclosed function must return an nested function.

When to use closure?

So, what is the use of closure?

Closures can avoid the use of 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 to be 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 better 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
# 3multiplication
times3 = make_multiplier_of(3)
# 5multiplication
times5 = make_multiplier_of(5)
# Output: 27
print(times3(9))
# Output: 15
print(times5(3))
# Output: 30
print(times5(times3(2))

Python decorators are alsoA large number 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