Explicación de Closures en Python: Cómo las Funciones Anidadas Capturan Variables
Closures en Python
Descubre cómo funcionan los closures en Python, cómo definirlos y por qué son esenciales para código limpio y eficiente.
Variables Nonlocal en una Función Anidada
Antes de explorar closures, es crucial entender funciones anidadas y variables nonlocal. Una función definida dentro de otra función se llama función anidada. Tales funciones pueden leer variables de su ámbito envolvente.
En Python, estas variables non-local son de solo lectura por defecto. Para modificarlas, debes declarar explícitamente la variable como nonlocal dentro de la función anidada.
Abajo un ejemplo simple mostrando una función anidada accediendo a una variable non-local.
def print_msg(msg):
# Función externa
def printer():
# Función anidada
print(msg)
printer() # Ejecutar
print_msg("Hola")
Salida
Hola
La función anidada printer() puede acceder a la variable msg de su ámbito externo.
Definir una Función Closure
¿Qué pasa si la función externa retornara la función anidada en lugar de llamarla? El código se vería así:
def print_msg(msg):
def printer():
print(msg)
return printer # Retornar la función anidada
# Almacenar la función retornada
another = print_msg("Hola")
another()
Salida
Hola
Observa que la función printer aún recuerda el valor de msg incluso después de que print_msg ha terminado de ejecutarse. Este fenómeno —donde una función retiene acceso a variables de su ámbito de definición— se llama closure en Python.
Para ilustrar más, elimina la función original y ve que la función retornada aún funciona:
>>> del print_msg
>>> another()
Hola
>>> print_msg("Hola")
Traceback (most recent call last):
... NameError: name 'print_msg' is not defined
La función retornada continúa funcionando porque capturó los datos necesarios en su closure.
¿Cuándo Tenemos Closures?
En Python, un closure existe cuando una función anidada:
- está definida dentro de otra función.
- referencia una variable de su función envolvente.
- es retornada por la función externa.
¿Cuándo Usar Closures?
Los closures ofrecen varias ventajas:
- Eliminan la necesidad de variables globales, mejorando encapsulación.
- Proporcionan una alternativa ligera a clases de un solo método, manteniendo código conciso.
- Habilitan patrones funcionales como decoradores, donde una función wrapper necesita acceso a los argumentos de la función original.
Abajo un ejemplo común: una fábrica que crea funciones multiplicadoras.
def make_multiplier_of(n):
def multiplier(x):
return x * n
return multiplier
# Crear multiplicadores específicos
times3 = make_multiplier_of(3)
times5 = make_multiplier_of(5)
print(times3(9)) # 27
print(times5(3)) # 15
print(times5(times3(2))) # 30
Salida
27 15 30
La sintaxis de decoradores de Python depende fuertemente de closures. Cuando escribes un decorador, la función wrapper captura la función que decora, formando un closure.
Para inspeccionar un closure, usa el atributo __closure__. Devuelve una tupla de objetos cell que contienen los valores encerrados. Por ejemplo:
>>> make_multiplier_of.__closure__
>>> times3.__closure__
(<cell at 0x0000000002D155B8: int object at 0x000000001E39B6E0>,)
El atributo cell_contents de cada cell contiene el valor real capturado por el closure:
>>> times3.__closure__[0].cell_contents
3
>>> times5.__closure__[0].cell_contents
5
Entender closures te permite escribir código Python más limpio y modular que evita globales innecesarios y abraza paradigmas funcionales.
python
- Dominando tipos de datos en Python: Guía práctica
- Dominando operadores en Python: Guía completa
- Dominando la sentencia pass en Python: Guía práctica
- Funciones lambda en Python: Guía práctica de funciones anónimas
- Dominando Diccionarios en Python: Creación, Manipulación y Técnicas Avanzadas
- Generadores en Python: Iteración Eficiente y Casos de Uso Avanzados
- Dominando Decoradores en Python: Mejora Funciones con Técnicas Expertas
- Domine el Método strip() de Python: Guía Completa y Ejemplos Prácticos
- Dominando las funciones lambda en Python: ejemplos prácticos y mejores prácticas
- Función abs() en Python: calcular valores absolutos para números y complejos
- Función round() en Python explicada con ejemplos prácticos