3.1 Introducción a los cierres
Un cierre es una función que captura variables de su ámbito circundante, incluso después de que este ámbito haya terminado su ejecución. Esto significa que un cierre puede «recordar» los valores de las variables de su ámbito externo y seguir utilizándolos, incluso cuando ese ámbito ya no está activo.
Para entender cómo funcionan los cierres, veamos el siguiente ejemplo:
def outer_function(x):
def inner_function(y):
return x + y
return inner_function
closure = outer_function(10)
print(closure(5)) # Salida: 15
Vamos a desglosar lo que aquí está escrito:
Función externa (outer_function): Esta función toma un argumento x y define una función interna inner_function, que toma un argumento y y devuelve la suma de x y y. La función inner_function no se llama dentro de outer_function, solo se declara.
Función interna (inner_function): Esta función se devuelve desde outer_function y mantiene dentro de sí una referencia al valor de x, que se pasa a outer_function.
Cierre: La variable closure se convierte en un cierre que «recuerda» el valor de x (en este caso, 10) y puede usarlo cuando se llama.
Normalmente, nadie es capaz de trabajar con cierres correctamente a la primera. Así que vamos a tratar de mejorar tu comprensión de los cierres mediante ejemplos.
3.2 Ejemplos de uso de cierres
Creación de una función generadora
Los cierres pueden ser utilizados para crear funciones generadoras que generen secuencias de valores.
def make_counter():
count = 0
def counter():
nonlocal count
count += 1
return count
return counter
counter = make_counter()
print(counter()) # Salida: 1
print(counter()) # Salida: 2
print(counter()) # Salida: 3
Explicación:
Función generadora (make_counter): Esta función crea una variable count y devuelve una función interna counter, que incrementa el valor de count y lo devuelve.
Cierre: La función counter mantiene el estado de la variable count y puede modificarlo en cada llamada.
Creación de una función con configuración
Los cierres pueden ser utilizados para crear funciones con una configuración predefinida.
def make_multiplier(factor):
def multiplier(x):
return x * factor
return multiplier
double = make_multiplier(2)
triple = make_multiplier(3)
print(double(5)) # Salida: 10
print(triple(5)) # Salida: 15
Explicación:
Función configuradora (make_multiplier): Esta función toma un multiplicador factor y devuelve una función interna multiplier, que multiplica el valor de entrada por factor.
Cierres: Las funciones double y triple son cierres, que mantienen sus propios valores de factor y los utilizan para multiplicar.
Filtración de datos con parámetros
Los cierres pueden ser útiles para crear funciones de filtrado con parámetros.
def make_filter(threshold):
def filter_func(value):
return value > threshold
return filter_func
filter_above_10 = make_filter(10)
data = [5, 10, 15, 20]
filtered_data = list(filter(filter_above_10, data))
print(filtered_data) # Salida: [15, 20]
Explicación:
Función de filtro (make_filter): Esta función toma un valor umbral threshold y devuelve una función interna filter_func, que verifica si el valor excede el umbral.
Cierre: La función filter_func guarda el valor threshold y lo usa para filtrar los datos.
3.3 Ventajas y desventajas de los cierres
Ventajas del uso de cierres
Encapsulación de estado: Los cierres permiten encapsular el estado dentro de la función, evitando variables globales y mejorando la legibilidad y el mantenimiento del código.
Flexibilidad: Los cierres pueden ser utilizados para crear funciones con una configuración o comportamiento específicos, haciendo que el código sea más flexible y adaptable.
Programación funcional: Los cierres son un concepto importante en la programación funcional, permitiendo crear funciones de orden superior y otras construcciones funcionales.
Limitaciones y problemas potenciales
A pesar de las muchas ventajas, los cierres tienen sus limitaciones:
Uso de memoria: Los cierres pueden mantener referencias a objetos que ya no se utilizan, lo que puede llevar a fugas de memoria.
Complejidad de depuración: Los cierres pueden complicar la depuración del código, ya que los estados de las variables pueden no ser evidentes.
GO TO FULL VERSION