En programación funcional, una función pura cumple dos condiciones:
Mismo input → mismo output: dados los mismos argumentos, siempre retorna el mismo resultado
Sin efectos secundarios (side effects): no modifica nada fuera de su propio scope
Un side effect es cualquier cosa que la función hace además de calcular y retornar su valor: imprimir, modificar variables globales, leer archivos, llamar a random(), etc.
python
# IMPURA: modifica variable externa (side effect)
mi_lista = [1, 2, 3]
defagregar_impura(numero):
mi_lista.append(numero) # modifica estado externo
# IMPURA: print es side effect
defaumentar_impura(x):
print('retornando', x + 1) # side effect
return x + 1
# IMPURA: random() no es determinista
from random import random
defescalar_random(x):
return x * random()
# PURA: solo depende de sus argumentos
from copy import deepcopy
defagregar_pura(lista, numero):
copia = deepcopy(lista) # no toca la lista original
copia.append(numero)
return copia
La pureza habilita caching con @cache: como el resultado siempre es el mismo para el mismo input, Python puede memorizar resultados y no recalcularlos. Esto no es posible con funciones impuras.
Tip
Cargando Quiz...
Cargando Quiz...
functions
Funciones lambda
Una función lambda es una función anónima definida en una sola línea:
lambda parámetros: expresión
No necesita return — la expresión ES el valor retornado
No puede contener statements (for, while, if/else con cuerpo) — solo expresiones
Puede asignarse a una variable o usarse directamente como argumento (inline)
reduce de functools aplica una función binaria acumulativamente sobre un iterable, produciendo un único valor:
reduce(f, [a, b, c, d]) → f(f(f(a, b), c), d)
Con inicializador: reduce(f, iterable, val_inicial) — el valor inicial actúa como primer acumulado antes de la lista
Lista vacía sin inicializador → TypeError
Lista con un solo elemento → retorna ese elemento sin aplicar f nunca
print(reduce(lambda x, y: x + y, sublistas)) # [1, 2, 3, 4, 5, 6]
# Lista vacía SIN inicializador: TypeError
# reduce(lambda x, y: x + y, []) ← lanza TypeError
# Con inicializador: OK
print(reduce(lambda x, y: x + y, [], 0)) # 0
Cargando Quiz...
Cargando Quiz...
Cargando Quiz...
notas = [6.5, 4.0, 5.5]
for nombre, nota inzip(nombres, notas):
print(f'{nombre}: {nota}')
# Ana: 6.5 / Luis: 4.0 / Maria: 5.5
# zip para al mas corto
a = [1, 2, 3]
b = ['x', 'y'] # mas corto
print(list(zip(a, b))) # [(1, 'x'), (2, 'y')] — el 3 queda sin par
# zip(*lista) invierte zip
pares = [(1, 'a'), (2, 'b'), (3, 'c')]
nums, letras = zip(*pares)
print(list(nums)) # [1, 2, 3]
print(list(letras)) # ['a', 'b', 'c']
Para zip que tome el iterable más largo (rellenando con None u otro valor), usa itertools.zip_longest. El zip estándar siempre descarta los elementos sin pareja.