Python

Python

Tutorial Python: Funciones lambda

Aprende la sintaxis, asignación y funciones que retornan funciones con lambdas en Python para código conciso y funcional.

Aprende Python y certifícate

Sintaxis básica

Las funciones lambda en Python son una forma concisa de crear funciones anónimas de una sola línea. A diferencia de las funciones definidas con def, las lambdas no necesitan un nombre y están diseñadas para operaciones simples y específicas.

La sintaxis básica de una función lambda sigue este patrón:

lambda argumentos: expresión

Donde:

  • La palabra clave lambda indica que estamos creando una función anónima
  • argumentos son los parámetros que recibe la función (pueden ser cero o más)
  • Los dos puntos : separan los argumentos de la expresión
  • expresión es una única operación que se evalúa y devuelve automáticamente

Veamos algunos ejemplos sencillos para entender mejor la sintaxis:

  • Lambda sin argumentos:
saludo = lambda: "Hola mundo"
print(saludo())  # Imprime: Hola mundo
  • Lambda con un argumento:
cuadrado = lambda x: x ** 2
print(cuadrado(5))  # Imprime: 25
  • Lambda con múltiples argumentos:
suma = lambda a, b: a + b
print(suma(3, 4))  # Imprime: 7
  • Lambda con argumentos por defecto:
incrementar = lambda x, incremento=1: x + incremento
print(incrementar(10))      # Imprime: 11
print(incrementar(10, 5))   # Imprime: 15

Las funciones lambda son particularmente útiles cuando necesitamos pasar una función simple como argumento a otra función, como en el caso de map(), filter() o sorted():

# Usando lambda con map para convertir una lista de strings a enteros
numeros_texto = ["1", "2", "3", "4"]
numeros = list(map(lambda x: int(x), numeros_texto))
print(numeros)  # Imprime: [1, 2, 3, 4]

# Usando lambda con filter para obtener solo números pares
numeros = [1, 2, 3, 4, 5, 6]
pares = list(filter(lambda x: x % 2 == 0, numeros))
print(pares)  # Imprime: [2, 4, 6]

# Usando lambda con sorted para ordenar una lista de tuplas por el segundo elemento
datos = [("manzana", 3), ("naranja", 1), ("pera", 2)]
ordenados = sorted(datos, key=lambda x: x[1])
print(ordenados)  # Imprime: [('naranja', 1), ('pera', 2), ('manzana', 3)]

Limitaciones de las funciones lambda

Es importante entender las restricciones de las funciones lambda:

  • Solo pueden contener una única expresión (no sentencias)
  • No pueden contener asignaciones (=)
  • No pueden incluir instrucciones como return, pass, assert, etc.
  • No permiten documentación (docstrings)
# Esto NO funcionaría en una lambda:
# error_lambda = lambda x: if x > 0: return x else: return -x

# En su lugar, podemos usar el operador ternario:
valor_absoluto = lambda x: x if x > 0 else -x
print(valor_absoluto(-5))  # Imprime: 5

Comparación con funciones regulares

Para entender mejor cuándo usar lambdas, veamos la equivalencia entre una función regular y una lambda:

# Función regular
def cubo(x):
    return x ** 3

# Equivalente como lambda
cubo_lambda = lambda x: x ** 3

# Ambas funcionan igual
print(cubo(3))        # Imprime: 27
print(cubo_lambda(3)) # Imprime: 27

Las lambdas son ideales cuando la operación es simple y se puede expresar en una línea. Para operaciones más complejas, las funciones regulares son más apropiadas y legibles.

# Operación simple: ideal para lambda
multiplicar = lambda x, y: x * y

# Operación compleja: mejor como función regular
def calcular_descuento(precio, porcentaje, minimo=0):
    descuento = precio * (porcentaje / 100)
    if descuento < minimo:
        return minimo
    return descuento

La sintaxis de las funciones lambda es una herramienta poderosa para escribir código más conciso y funcional en Python, especialmente cuando trabajamos con funciones de orden superior que esperan otras funciones como argumentos.

Asignar función lambda a variable

Aunque las funciones lambda son anónimas por naturaleza, Python permite asignarlas a variables para reutilizarlas en diferentes partes del código. Esta técnica combina la concisión de las lambdas con la capacidad de referencia de las funciones nombradas.

Cuando asignamos una lambda a una variable, estamos creando una referencia a esa función anónima que podemos invocar posteriormente:

# Asignación de una lambda a una variable
convertir_a_celsius = lambda fahrenheit: (fahrenheit - 32) * 5/9

# Uso de la función lambda a través de la variable
temperatura = convertir_a_celsius(98.6)
print(f"98.6°F equivale a {temperatura:.1f}°C")  # Imprime: 98.6°F equivale a 37.0°C

Esta asignación nos permite reutilizar la función lambda sin tener que reescribirla cada vez:

temperaturas_f = [32, 68, 86, 104, 212]
temperaturas_c = [convertir_a_celsius(temp) for temp in temperaturas_f]
print(temperaturas_c)  # Imprime: [0.0, 20.0, 30.0, 40.0, 100.0]

Ventajas de asignar lambdas a variables

Asignar lambdas a variables ofrece varios beneficios prácticos:

  • Legibilidad mejorada: Da un nombre descriptivo a operaciones anónimas
  • Reutilización: Permite usar la misma función en múltiples lugares
  • Depuración: Facilita la identificación de la función en mensajes de error
# Lambda asignada con nombre descriptivo
calcular_iva = lambda precio: precio * 0.21
precio_con_iva = calcular_iva(100)
print(precio_con_iva)  # Imprime: 21.0

Lambdas en estructuras de datos

Las lambdas asignadas a variables pueden almacenarse en estructuras de datos como listas, diccionarios o tuplas:

# Colección de operaciones matemáticas como lambdas
operaciones = {
    'suma': lambda a, b: a + b,
    'resta': lambda a, b: a - b,
    'multiplicacion': lambda a, b: a * b,
    'division': lambda a, b: a / b if b != 0 else "Error: División por cero"
}

# Uso de las operaciones almacenadas
print(operaciones['suma'](10, 5))         # Imprime: 15
print(operaciones['multiplicacion'](3, 4)) # Imprime: 12

Este enfoque es especialmente útil para implementar estrategias o comportamientos intercambiables:

# Diferentes estrategias de descuento como lambdas
estrategias_descuento = {
    'ninguno': lambda precio: precio,
    'porcentaje': lambda precio, porcentaje=10: precio * (1 - porcentaje/100),
    'fijo': lambda precio, cantidad=5: precio - cantidad if precio > cantidad else 0
}

# Aplicar diferentes estrategias según el caso
producto = 100
print(estrategias_descuento['ninguno'](producto))           # Imprime: 100
print(estrategias_descuento['porcentaje'](producto, 20))    # Imprime: 80.0
print(estrategias_descuento['fijo'](producto, 25))          # Imprime: 75

Comparación con funciones nombradas

Aunque asignar lambdas a variables puede parecer similar a definir funciones con def, existen diferencias importantes:

# Función lambda asignada a variable
duplicar_lambda = lambda x: x * 2

# Función equivalente con def
def duplicar_funcion(x):
    return x * 2

# Comparación de representaciones
print(duplicar_lambda)    # Muestra: <function <lambda> at 0x...>
print(duplicar_funcion)   # Muestra: <function duplicar_funcion at 0x...>

Observa que incluso después de asignarla a una variable, Python sigue considerando la lambda como una función anónima en su representación interna.

Casos de uso prácticos

Las lambdas asignadas a variables son particularmente útiles en estos escenarios:

  • Transformaciones de datos que se aplican repetidamente:
normalizar = lambda texto: texto.lower().strip()

datos = [" Python ", "JAVASCRIPT", "  Ruby  "]
datos_normalizados = [normalizar(item) for item in datos]
print(datos_normalizados)  # Imprime: ['python', 'javascript', 'ruby']
  • Validadores simples que se usan en múltiples lugares:
es_email_valido = lambda email: "@" in email and "." in email.split("@")[1]

emails = ["usuario@dominio.com", "invalido@", "otro@ejemplo.com"]
emails_validos = [email for email in emails if es_email_valido(email)]
print(emails_validos)  # Imprime: ['usuario@dominio.com', 'otro@ejemplo.com']
  • Funciones de conversión que se aplican a conjuntos de datos:
a_formato_moneda = lambda valor: f"${valor:.2f}"

precios = [19.99, 5.50, 3.45, 999]
precios_formateados = list(map(a_formato_moneda, precios))
print(precios_formateados)  # Imprime: ['$19.99', '$5.50', '$3.45', '$999.00']

Asignar lambdas a variables es una técnica que equilibra la concisión del código con la claridad y reutilización, permitiéndote aprovechar la sintaxis compacta de las lambdas sin sacrificar la legibilidad de tu código.

Función que retorna función

En Python, las funciones son objetos de primera clase, lo que significa que pueden ser tratadas como cualquier otro valor: pasadas como argumentos, asignadas a variables y, lo que exploraremos en esta sección, retornadas desde otras funciones. Esta capacidad es fundamental para técnicas avanzadas de programación funcional.

Una función que retorna otra función crea lo que se conoce como clausura (closure), donde la función interna "recuerda" el entorno en el que fue creada, incluso después de que la función externa haya terminado su ejecución.

Veamos un ejemplo básico utilizando funciones lambda:

def crear_multiplicador(factor):
    return lambda x: x * factor

# Creamos funciones específicas a partir de la función generadora
duplicar = crear_multiplicador(2)
triplicar = crear_multiplicador(3)

# Utilizamos las funciones generadas
print(duplicar(5))   # Imprime: 10
print(triplicar(5))  # Imprime: 15

En este ejemplo, crear_multiplicador es una función generadora que retorna una función lambda. El parámetro factor queda "capturado" en la clausura, creando funciones especializadas.

Creación de funciones personalizadas en tiempo de ejecución

Esta técnica nos permite generar funciones dinámicamente según las necesidades de nuestro programa:

def crear_formateador(prefijo, sufijo=""):
    return lambda texto: f"{prefijo}{texto}{sufijo}"

# Creamos diferentes formateadores
negrita = crear_formateador("**", "**")
cursiva = crear_formateador("_", "_")
codigo = crear_formateador("`", "`")

# Aplicamos los formateadores
texto = "Python"
print(negrita(texto))  # Imprime: **Python**
print(cursiva(texto))  # Imprime: _Python_
print(codigo(texto))   # Imprime: `Python`

Cada función retornada mantiene su propio contexto con los valores específicos de prefijo y sufijo.

Funciones de orden superior con lambdas

Las funciones que retornan funciones son especialmente útiles para crear transformadores o procesadores genéricos:

def aplicar_operacion(operacion):
    if operacion == "suma":
        return lambda a, b: a + b
    elif operacion == "resta":
        return lambda a, b: a - b
    elif operacion == "multiplicacion":
        return lambda a, b: a * b
    else:
        return lambda a, b: a / b if b != 0 else None

# Obtenemos la función deseada
calcular = aplicar_operacion("suma")
print(calcular(10, 5))  # Imprime: 15

# Podemos cambiar la operación según necesitemos
calcular = aplicar_operacion("multiplicacion")
print(calcular(10, 5))  # Imprime: 50

Creación de decoradores simples

Los decoradores en Python son un caso especial de funciones que retornan funciones. Podemos crear decoradores simples usando lambdas:

def registrar_llamada(funcion):
    return lambda *args, **kwargs: (
        print(f"Llamando a {funcion.__name__} con {args} y {kwargs}"),
        funcion(*args, **kwargs)
    )[1]

# Función normal
def saludar(nombre):
    return f"Hola, {nombre}"

# Aplicamos el decorador manualmente
saludar_con_registro = registrar_llamada(saludar)

# Al llamar a la función decorada, veremos el registro
resultado = saludar_con_registro("Ana")
# Imprime: Llamando a saludar con ('Ana',) y {}
print(resultado)  # Imprime: Hola, Ana

Currying con lambdas

El currying es una técnica donde convertimos una función que toma múltiples argumentos en una secuencia de funciones que toman un solo argumento. Las lambdas son ideales para implementar esta técnica:

def curry(f):
    # Función que implementa currying para una función de dos argumentos
    return lambda x: lambda y: f(x, y)

# Función normal de dos argumentos
def dividir(a, b):
    return a / b if b != 0 else None

# Versión currificada
dividir_curry = curry(dividir)

# Creamos una función especializada que divide por 2
dividir_entre_2 = dividir_curry(2)

# Usamos la función especializada
print(dividir_entre_2(10))  # Imprime: 0.2 (2/10)

Fábricas de validadores

Podemos crear fábricas de funciones que generen validadores específicos:

def crear_validador(min_longitud, caracteres_especiales=False):
    def validar(password):
        if len(password) < min_longitud:
            return False
        if caracteres_especiales and not any(c in "!@#$%^&*" for c in password):
            return False
        return True
    
    return validar

# Creamos diferentes validadores
validador_basico = crear_validador(8)
validador_seguro = crear_validador(10, True)

# Probamos contraseñas
print(validador_basico("abc123"))      # Imprime: False (muy corta)
print(validador_basico("abcdefgh"))    # Imprime: True
print(validador_seguro("abcdefghij"))  # Imprime: False (sin caracteres especiales)
print(validador_seguro("abcdef!hij"))  # Imprime: True

Memoización con funciones que retornan funciones

La memoización es una técnica de optimización que almacena resultados de llamadas a funciones para evitar cálculos repetidos. Podemos implementarla fácilmente con funciones que retornan funciones:

def memoizar(funcion):
    cache = {}
    
    def wrapper(*args):
        if args not in cache:
            cache[args] = funcion(*args)
        return cache[args]
    
    return wrapper

# Función costosa (ejemplo: cálculo de Fibonacci)
def fibonacci(n):
    if n <= 1:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

# Versión memoizada
fibonacci_rapido = memoizar(lambda n: 
    n if n <= 1 else fibonacci_rapido(n-1) + fibonacci_rapido(n-2)
)

# Comparación de rendimiento
import time

inicio = time.time()
resultado1 = fibonacci(30)  # Muy lento
tiempo1 = time.time() - inicio

inicio = time.time()
resultado2 = fibonacci_rapido(30)  # Mucho más rápido
tiempo2 = time.time() - inicio

print(f"Resultado: {resultado2}")
print(f"Tiempo sin memoización: {tiempo1:.2f}s")
print(f"Tiempo con memoización: {tiempo2:.2f}s")

Composición de funciones

La composición de funciones es otra técnica poderosa que podemos implementar con funciones que retornan funciones:

def componer(*funciones):
    def composicion(x):
        resultado = x
        for f in reversed(funciones):
            resultado = f(resultado)
        return resultado
    return composicion

# Funciones simples para componer
cuadrado = lambda x: x ** 2
incrementar = lambda x: x + 1
duplicar = lambda x: x * 2

# Creamos diferentes composiciones
f1 = componer(cuadrado, incrementar)       # (x + 1)²
f2 = componer(incrementar, cuadrado)       # x² + 1
f3 = componer(duplicar, incrementar, cuadrado)  # (x² + 1) * 2

# Probamos las composiciones
x = 3
print(f1(x))  # Imprime: 16 ((3 + 1)²)
print(f2(x))  # Imprime: 10 (3² + 1)
print(f3(x))  # Imprime: 20 ((3² + 1) * 2)

Las funciones que retornan funciones son una herramienta poderosa en el arsenal de programación funcional de Python, permitiéndonos crear código más modular, reutilizable y expresivo. Combinadas con lambdas, nos ofrecen una forma elegante de implementar patrones avanzados como clausuras, currying, memoización y composición de funciones.

Aprende Python online

Otros ejercicios de programación de Python

Evalúa tus conocimientos de esta lección Funciones lambda con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.

Módulo math

Python
Puzzle

Reto herencia

Python
Código

Excepciones

Python
Test

Introducción a Python

Python
Test

Reto variables

Python
Código

Funciones Python

Python
Puzzle

Reto funciones

Python
Código

Módulo datetime

Python
Test

Reto acumulación

Python
Código

Reto estructuras condicionales

Python
Código

Polimorfismo

Python
Test

Módulo os

Python
Test

Reto métodos dunder

Python
Código

Diccionarios

Python
Puzzle

Reto clases y objetos

Python
Código

Reto operadores

Python
Código

Operadores

Python
Test

Estructuras de control

Python
Puzzle

Funciones lambda

Python
Test

Reto diccionarios

Python
Código

Reto función lambda

Python
Código

Encapsulación

Python
Puzzle

Reto coleciones

Python
Proyecto

Reto funciones auxiliares

Python
Código

Crear módulos y paquetes

Python
Puzzle

Módulo datetime

Python
Puzzle

Excepciones

Python
Puzzle

Operadores

Python
Puzzle

Diccionarios

Python
Test

Reto map, filter

Python
Código

Reto tuplas

Python
Código

Proyecto gestor de tareas CRUD

Python
Proyecto

Tuplas

Python
Puzzle

Variables

Python
Puzzle

Tipos de datos

Python
Puzzle

Conjuntos

Python
Test

Reto mixins

Python
Código

Módulo csv

Python
Test

Módulo json

Python
Test

Herencia

Python
Test

Análisis de datos de ventas con Pandas

Python
Proyecto

Reto fechas y tiempo

Python
Proyecto

Reto estructuras de iteración

Python
Código

Funciones

Python
Test

Reto comprehensions

Python
Código

Variables

Python
Test

Reto serialización

Python
Proyecto

Módulo csv

Python
Puzzle

Reto polimorfismo

Python
Código

Polimorfismo

Python
Puzzle

Clases y objetos

Python
Código

Reto encapsulación

Python
Código

Estructuras de control

Python
Test

Importar módulos y paquetes

Python
Test

Módulo math

Python
Test

Funciones lambda

Python
Puzzle

Reto excepciones

Python
Código

Listas

Python
Puzzle

Reto archivos

Python
Proyecto

Encapsulación

Python
Test

Reto conjuntos

Python
Código

Clases y objetos

Python
Test

Instalación de Python y creación de proyecto

Python
Test

Reto listas

Python
Código

Tipos de datos

Python
Test

Crear módulos y paquetes

Python
Test

Tuplas

Python
Test

Herencia

Python
Puzzle

Reto acceso a sistema

Python
Proyecto

Proyecto sintaxis calculadora

Python
Proyecto

Importar módulos y paquetes

Python
Puzzle

Clases y objetos

Python
Puzzle

Módulo os

Python
Puzzle

Listas

Python
Test

Conjuntos

Python
Puzzle

Reto tipos de datos

Python
Código

Reto matemáticas

Python
Proyecto

Módulo json

Python
Puzzle

Todas las lecciones de Python

Accede a todas las lecciones de Python y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Introducción A Python

Python

Introducción

Instalación Y Creación De Proyecto

Python

Introducción

Tema 2: Tipos De Datos, Variables Y Operadores

Python

Introducción

Instalación De Python

Python

Introducción

Tipos De Datos

Python

Sintaxis

Variables

Python

Sintaxis

Operadores

Python

Sintaxis

Estructuras De Control

Python

Sintaxis

Funciones

Python

Sintaxis

Estructuras Control Iterativo

Python

Sintaxis

Estructuras Control Condicional

Python

Sintaxis

Testing Con Pytest

Python

Sintaxis

Listas

Python

Estructuras De Datos

Tuplas

Python

Estructuras De Datos

Diccionarios

Python

Estructuras De Datos

Conjuntos

Python

Estructuras De Datos

Comprehensions

Python

Estructuras De Datos

Clases Y Objetos

Python

Programación Orientada A Objetos

Excepciones

Python

Programación Orientada A Objetos

Encapsulación

Python

Programación Orientada A Objetos

Herencia

Python

Programación Orientada A Objetos

Polimorfismo

Python

Programación Orientada A Objetos

Mixins Y Herencia Múltiple

Python

Programación Orientada A Objetos

Métodos Especiales (Dunder Methods)

Python

Programación Orientada A Objetos

Composición De Clases

Python

Programación Orientada A Objetos

Funciones Lambda

Python

Programación Funcional

Aplicación Parcial

Python

Programación Funcional

Entrada Y Salida, Manejo De Archivos

Python

Programación Funcional

Decoradores

Python

Programación Funcional

Generadores

Python

Programación Funcional

Paradigma Funcional

Python

Programación Funcional

Composición De Funciones

Python

Programación Funcional

Funciones Orden Superior Map Y Filter

Python

Programación Funcional

Funciones Auxiliares

Python

Programación Funcional

Reducción Y Acumulación

Python

Programación Funcional

Archivos Comprimidos

Python

Entrada Y Salida Io

Entrada Y Salida Avanzada

Python

Entrada Y Salida Io

Archivos Temporales

Python

Entrada Y Salida Io

Contexto With

Python

Entrada Y Salida Io

Módulo Csv

Python

Biblioteca Estándar

Módulo Json

Python

Biblioteca Estándar

Módulo Datetime

Python

Biblioteca Estándar

Módulo Math

Python

Biblioteca Estándar

Módulo Os

Python

Biblioteca Estándar

Módulo Re

Python

Biblioteca Estándar

Módulo Random

Python

Biblioteca Estándar

Módulo Time

Python

Biblioteca Estándar

Módulo Collections

Python

Biblioteca Estándar

Módulo Sys

Python

Biblioteca Estándar

Módulo Statistics

Python

Biblioteca Estándar

Módulo Pickle

Python

Biblioteca Estándar

Módulo Pathlib

Python

Biblioteca Estándar

Importar Módulos Y Paquetes

Python

Paquetes Y Módulos

Crear Módulos Y Paquetes

Python

Paquetes Y Módulos

Entornos Virtuales (Virtualenv, Venv)

Python

Entorno Y Dependencias

Gestión De Dependencias (Pip, Requirements.txt)

Python

Entorno Y Dependencias

Python-dotenv Y Variables De Entorno

Python

Entorno Y Dependencias

Acceso A Datos Con Mysql, Pymongo Y Pandas

Python

Acceso A Bases De Datos

Acceso A Mongodb Con Pymongo

Python

Acceso A Bases De Datos

Acceso A Mysql Con Mysql Connector

Python

Acceso A Bases De Datos

Novedades Python 3.13

Python

Características Modernas

Operador Walrus

Python

Características Modernas

Pattern Matching

Python

Características Modernas

Instalación Beautiful Soup

Python

Web Scraping

Sintaxis General De Beautiful Soup

Python

Web Scraping

Tipos De Selectores

Python

Web Scraping

Web Scraping De Html

Python

Web Scraping

Web Scraping Para Ciencia De Datos

Python

Web Scraping

Autenticación Y Acceso A Recursos Protegidos

Python

Web Scraping

Combinación De Selenium Con Beautiful Soup

Python

Web Scraping

Accede GRATIS a Python y certifícate

En esta lección

Objetivos de aprendizaje de esta lección

  • Comprender la sintaxis básica y limitaciones de las funciones lambda en Python.
  • Aprender a asignar funciones lambda a variables para mejorar la reutilización y legibilidad.
  • Explorar el uso de funciones que retornan funciones y su aplicación en clausuras y currying.
  • Conocer casos prácticos como decoradores, memoización y composición de funciones usando lambdas.
  • Diferenciar cuándo es más adecuado usar funciones lambda o funciones regulares definidas con def.