A1.A Funciones como valores¶
Para quién es esto
Es material avanzado: da por sabidas las unidades 1 a 5 (variables, estructuras de control, colecciones y clases). Si alguna idea se te resiste, vuelve a la unidad correspondiente.
Hasta ahora has llamado funciones. Aquí das un paso más: tratar una función como un valor. Se puede guardar en una variable, pasar a otra función y devolver desde una función. Es la base de cosas que ya usas sin darte cuenta: ordenar con un criterio, reaccionar a un clic o filtrar una lista.
Tipo de una función en Python¶
En Python las funciones son objetos como cualquier otro: se guardan en variables, se pasan como argumento y se devuelven. No hace falta declarar su tipo. lambda n: n * 2 crea una función anónima de una sola expresión; para algo más largo se define una función con def y se pasa por su nombre, sin paréntesis.
Un ejemplo con todo¶
El programa define una función, la pasa a otra, devuelve una función desde una función y crea dos contadores independientes:
def doble(n):
return n * 2
# Recibe una función como parámetro
def aplicar_dos_veces(f, x):
return f(f(x))
# Devuelve una función que "recuerda" factor
def multiplicador(factor):
return lambda n: n * factor
# Cierre: la función interna recuerda y modifica 'cuenta' (nonlocal permite modificarla)
def crear_contador():
cuenta = 0
def siguiente():
nonlocal cuenta
cuenta += 1
return cuenta
return siguiente
cuadrado = lambda n: n * n # función anónima guardada en una variable
print(f"doble(4) = {doble(4)}")
print(f"cuadrado(4) = {cuadrado(4)}")
print(f"aplicar dos veces doble a 3 = {aplicar_dos_veces(doble, 3)}")
print(f"multiplicador(5)(7) = {multiplicador(5)(7)}")
a = crear_contador()
b = crear_contador()
print(f"contador A: {a()} {a()} {a()}")
print(f"contador B: {b()}")
Salida:
doble(4) = 8
cuadrado(4) = 16
aplicar dos veces doble a 3 = 12
multiplicador(5)(7) = 35
contador A: 1 2 3
contador B: 1
Qué ocurre en cada línea:
| Línea de salida | Qué demuestra |
|---|---|
doble(4) y cuadrado(4) |
Una función con nombre y otra anónima guardada en una variable se llaman igual |
aplicar dos veces doble a 3 |
Una función recibe otra función como parámetro y la usa dos veces |
multiplicador(5)(7) |
Una función devuelve otra función, que recuerda el factor 5 |
contador A y contador B |
Cada contador recuerda su propia cuenta: no se pisan |
Cierres: funciones que recuerdan¶
Una función definida dentro de otra es un cierre: recuerda las variables de la función exterior aunque esta ya haya terminado. Para modificar una de esas variables (no solo leerla) hay que declararla con nonlocal; sin esa palabra, cuenta += 1 crearía una variable local nueva y daría error.
Cuándo usarlo
Si necesitas «una operación que se decide más tarde» (un criterio de orden, un filtro, qué hacer al terminar), pásala como función. Es más corto y más flexible que crear una clase solo para eso.
Errores frecuentes¶
| Error | Cómo evitarlo |
|---|---|
Llamar a la función al pasarla (doble(3) en vez de doble) |
Pasa el nombre sin paréntesis si quieres pasar la función, no su resultado |
| Esperar que cada llamada comparta o no comparta estado sin comprobarlo | Crea el cierre una vez por contador, como en el ejemplo |
| Escribir lambdas largas e ilegibles | Si pasa de una o dos líneas, ponle nombre a la función |
Para practicar¶
Los ejercicios A1.1 y A1.2 usan estas ideas. Para ver la misma idea escrita en los otros lenguajes: Pasar de uno a otro.