Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Usa la rueda del ratón o gestos táctiles para hacer zoom • Arrastra para mover

Parámetros y argumentos

🧭 Navegación:

¡Bienvenido al departamento de configuración de máquinas de nuestro almacén! Hasta ahora has aprendido a crear funciones básicas, pero ahora vamos a convertirlas en máquinas súper flexibles que pueden adaptarse a diferentes situaciones. Los parámetros y argumentos son como los controles y configuraciones que hacen que una máquina sea versátil.

🔧 ¿Qué son los parámetros y argumentos?

Imagina que tienes una máquina etiquetadora en tu almacén. Esta máquina puede crear etiquetas, pero necesita que le digas:

  • ¿Qué texto poner?
  • ¿De qué color debe ser?
  • ¿Qué tamaño usar?

Estos “ajustes” que le das a la máquina son los argumentos, y los “controles” que tiene la máquina para recibir esos ajustes son los parámetros.

# Los parámetros son los "controles" de la máquina
def crear_etiqueta(texto, color, tamaño):
    """Máquina etiquetadora del almacén"""
    etiqueta = f"[{color.upper()}] {texto} (Tamaño: {tamaño})"
    return etiqueta

# Los argumentos son los "valores" que pasamos a esos controles
etiqueta1 = crear_etiqueta("FRÁGIL", "rojo", "grande")
etiqueta2 = crear_etiqueta("Electrónicos", "azul", "mediano")

📋 Tipos de parámetros

1. Parámetros obligatorios (posicionales)

Son como los controles esenciales de la máquina que SIEMPRE necesitas configurar:

def calcular_precio_envio(peso, distancia, tipo_envio):
    """
    Calcula el precio de envío de un producto.
    
    TODOS los parámetros son obligatorios - la máquina no funciona sin ellos.
    """
    precio_base = peso * 2.5  # $2.5 por kg
    precio_distancia = distancia * 0.1  # $0.1 por km
    
    multiplicador = {
        "express": 2.0,
        "normal": 1.0,
        "economico": 0.7
    }
    
    precio_final = (precio_base + precio_distancia) * multiplicador[tipo_envio]
    return precio_final

# TODOS los argumentos son obligatorios
precio = calcular_precio_envio(5.2, 150, "express")
print(f"Precio de envío: ${precio:.2f}")

# ❌ Esto dará error - faltan argumentos
# precio = calcular_precio_envio(5.2)  # Error: faltan distancia y tipo_envio

2. Parámetros opcionales (con valores por defecto)

Son como los controles con configuración automática - si no los ajustas, usan un valor por defecto:

def procesar_pedido(codigo_producto, cantidad, descuento=0, urgente=False, notas=""):
    """
    Procesa un pedido con configuraciones opcionales.
    
    Parámetros obligatorios: codigo_producto, cantidad
    Parámetros opcionales: descuento, urgente, notas
    """
    precio_base = obtener_precio(codigo_producto) * cantidad
    precio_con_descuento = precio_base * (1 - descuento/100)
    
    costo_urgente = 50 if urgente else 0
    precio_final = precio_con_descuento + costo_urgente
    
    pedido = {
        "codigo": codigo_producto,
        "cantidad": cantidad,
        "precio_final": precio_final,
        "urgente": urgente,
        "notas": notas if notas else "Sin notas especiales"
    }
    
    return pedido

# Usando solo parámetros obligatorios
pedido1 = procesar_pedido("LAP001", 2)

# Usando algunos parámetros opcionales
pedido2 = procesar_pedido("MOU001", 1, descuento=10)

# Usando todos los parámetros
pedido3 = procesar_pedido("TEC001", 1, descuento=15, urgente=True, notas="Cliente VIP")

3. Parámetros con palabras clave

Puedes especificar exactamente qué control quieres ajustar usando el nombre del parámetro:

def generar_reporte_inventario(categoria, incluir_agotados=True, ordenar_por="nombre", formato="texto"):
    """Genera un reporte personalizado del inventario"""
    print(f"Generando reporte de {categoria}")
    print(f"Incluir agotados: {incluir_agotados}")
    print(f"Ordenar por: {ordenar_por}")
    print(f"Formato: {formato}")

# Argumentos posicionales (en orden)
generar_reporte_inventario("Electrónicos", False, "precio", "PDF")

# Argumentos con palabras clave (cualquier orden)
generar_reporte_inventario(
    categoria="Electrónicos",
    formato="PDF", 
    ordenar_por="precio",
    incluir_agotados=False
)

# Mezclando posicionales y por palabra clave
generar_reporte_inventario("Electrónicos", ordenar_por="stock", formato="Excel")

🌟 Parámetros avanzados: *args y **kwargs

*args: Para listas variables de argumentos

Como una máquina que puede procesar cualquier cantidad de elementos:

def calcular_total_productos(*precios):
    """
    Calcula el total de productos sin importar cuántos sean.
    
    *precios recoge TODOS los argumentos posicionales en una tupla.
    """
    total = 0
    print(f"Procesando {len(precios)} productos:")
    
    for i, precio in enumerate(precios, 1):
        print(f"  Producto {i}: ${precio:.2f}")
        total += precio
    
    return total

# Puedes pasar cualquier cantidad de precios
total1 = calcular_total_productos(25.99)
total2 = calcular_total_productos(25.99, 89.50, 12.75)
total3 = calcular_total_productos(100, 200, 300, 400, 500)

print(f"Totales: ${total1:.2f}, ${total2:.2f}, ${total3:.2f}")

**kwargs: Para parámetros con nombre variables

Como una máquina súper configurable que acepta cualquier configuración que le envíes:

def crear_producto_personalizado(nombre, precio, **caracteristicas):
    """
    Crea un producto con características personalizables.
    
    **caracteristicas recoge TODOS los argumentos con nombre en un diccionario.
    """
    producto = {
        "nombre": nombre,
        "precio": precio
    }
    
    # Agregar todas las características adicionales
    producto.update(caracteristicas)
    
    print(f"📦 Producto: {nombre}")
    print(f"💰 Precio: ${precio:.2f}")
    print("🔧 Características adicionales:")
    
    for caracteristica, valor in caracteristicas.items():
        print(f"   {caracteristica}: {valor}")
    
    return producto

# Cada producto puede tener características diferentes
laptop = crear_producto_personalizado(
    "Laptop Gaming",
    1500.00,
    procesador="Intel i7",
    ram="16GB",
    almacenamiento="1TB SSD",
    tarjeta_grafica="RTX 4060",
    garantia="2 años"
)

mouse = crear_producto_personalizado(
    "Mouse Inalámbrico",
    35.99,
    conectividad="Bluetooth",
    bateria="6 meses",
    color="Negro"
)

Combinando *args y **kwargs

La máquina más flexible del almacén que acepta cualquier configuración:

def procesar_venta_flexible(vendedor, *productos, **opciones_venta):
    """
    Procesa una venta súper flexible.
    
    vendedor: Parámetro obligatorio
    *productos: Cualquier cantidad de productos
    **opciones_venta: Cualquier opción adicional
    """
    print(f"👨‍💼 Vendedor: {vendedor}")
    print(f"📦 Productos ({len(productos)}):")
    
    total = 0
    for i, producto in enumerate(productos, 1):
        print(f"   {i}. {producto['nombre']} - ${producto['precio']:.2f}")
        total += producto['precio']
    
    print(f"💰 Subtotal: ${total:.2f}")
    
    # Procesar opciones adicionales
    if opciones_venta:
        print("⚙️ Opciones especiales:")
        for opcion, valor in opciones_venta.items():
            print(f"   {opcion}: {valor}")
    
    # Aplicar descuentos si existen
    if 'descuento' in opciones_venta:
        descuento = total * (opciones_venta['descuento'] / 100)
        total -= descuento
        print(f"🎉 Descuento aplicado: -${descuento:.2f}")
    
    print(f"💳 Total final: ${total:.2f}")
    return total

# Ejemplo de uso súper flexible
venta = procesar_venta_flexible(
    "Ana García",  # vendedor (obligatorio)
    {"nombre": "Laptop", "precio": 1500},  # *productos
    {"nombre": "Mouse", "precio": 35},
    {"nombre": "Teclado", "precio": 120},
    descuento=10,  # **opciones_venta
    metodo_pago="tarjeta",
    cliente_vip=True,
    envio_express=True
)

🎯 Orden de los parámetros

En Python hay un orden específico que debes seguir al definir parámetros:

def funcion_completa(
    obligatorio1,              # 1. Parámetros posicionales obligatorios
    obligatorio2,
    opcional1="valor1",        # 2. Parámetros opcionales (con default)
    opcional2="valor2",
    *args,                     # 3. *args (argumentos posicionales variables)
    clave_solo1,               # 4. Keyword-only arguments
    clave_solo2="default",
    **kwargs                   # 5. **kwargs (argumentos con clave variables)
):
    """Función que muestra el orden correcto de parámetros"""
    print(f"Obligatorios: {obligatorio1}, {obligatorio2}")
    print(f"Opcionales: {opcional1}, {opcional2}")
    print(f"Args adicionales: {args}")
    print(f"Clave solo: {clave_solo1}, {clave_solo2}")
    print(f"Kwargs: {kwargs}")

# Ejemplo de uso
funcion_completa(
    "req1", "req2",           # obligatorios
    "opt1",                   # opcional1
    "extra1", "extra2",       # *args
    clave_solo1="valor",      # keyword-only
    parametro_extra="valor"   # **kwargs
)

🏭 Ejemplos prácticos del almacén

1. Sistema de descuentos flexible

def aplicar_descuentos(precio_base, *descuentos_porcentaje, cantidad=1, cliente_vip=False, **promociones):
    """
    Sistema flexible de descuentos del almacén.
    
    Args:
        precio_base: Precio original del producto
        *descuentos_porcentaje: Múltiples descuentos que se aplican secuencialmente
        cantidad: Cantidad de productos (con descuento por volumen)
        cliente_vip: Si es cliente VIP (descuento especial)
        **promociones: Promociones adicionales
    """
    precio_actual = precio_base
    
    print(f"💰 Precio base: ${precio_base:.2f}")
    
    # Aplicar descuentos secuenciales
    for i, descuento in enumerate(descuentos_porcentaje, 1):
        descuento_valor = precio_actual * (descuento / 100)
        precio_actual -= descuento_valor
        print(f"🎯 Descuento {i} ({descuento}%): -${descuento_valor:.2f} = ${precio_actual:.2f}")
    
    # Descuento por cantidad
    precio_total = precio_actual * cantidad
    if cantidad >= 5:
        descuento_volumen = precio_total * 0.05  # 5% por volumen
        precio_total -= descuento_volumen
        print(f"📦 Descuento por volumen (5%): -${descuento_volumen:.2f}")
    
    # Descuento VIP
    if cliente_vip:
        descuento_vip = precio_total * 0.10  # 10% VIP
        precio_total -= descuento_vip
        print(f"⭐ Descuento VIP (10%): -${descuento_vip:.2f}")
    
    # Promociones especiales
    for promo, valor in promociones.items():
        if promo == "codigo_promocional" and valor == "VERANO2024":
            descuento_promo = precio_total * 0.15
            precio_total -= descuento_promo
            print(f"🌞 Código promocional: -${descuento_promo:.2f}")
        elif promo == "descuento_adicional":
            precio_total -= valor
            print(f"💸 Descuento adicional: -${valor:.2f}")
    
    print(f"💳 PRECIO FINAL: ${precio_total:.2f}")
    return precio_total

# Ejemplo: múltiples descuentos en una venta compleja
precio_final = aplicar_descuentos(
    200.00,                    # precio_base
    10, 5,                     # descuentos del 10% y 5%
    cantidad=6,                # 6 productos (activa descuento por volumen)
    cliente_vip=True,          # cliente VIP
    codigo_promocional="VERANO2024",  # promoción especial
    descuento_adicional=20.00  # descuento extra
)

2. Generador de reportes configurables

def generar_reporte(titulo, *datos, formato="texto", incluir_fecha=True, 
                   separador="-", **metadatos):
    """
    Generador flexible de reportes del almacén.
    """
    from datetime import datetime
    
    # Encabezado del reporte
    linea_separador = separador * 50
    print(linea_separador)
    print(f"📊 {titulo.upper()}")
    
    if incluir_fecha:
        fecha_actual = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        print(f"📅 Generado: {fecha_actual}")
    
    # Metadatos adicionales
    if metadatos:
        print("ℹ️ Información adicional:")
        for clave, valor in metadatos.items():
            print(f"   {clave.replace('_', ' ').title()}: {valor}")
    
    print(linea_separador)
    
    # Datos del reporte
    if formato == "texto":
        for i, dato in enumerate(datos, 1):
            print(f"{i}. {dato}")
    elif formato == "lista":
        for dato in datos:
            print(f"• {dato}")
    elif formato == "numerado":
        for i, dato in enumerate(datos, 1):
            print(f"[{i:03d}] {dato}")
    
    print(linea_separador)
    print(f"📈 Total de elementos: {len(datos)}")
    
    return len(datos)

# Ejemplos de uso
reporte1 = generar_reporte(
    "Productos más vendidos",
    "Laptop Gaming - 45 unidades",
    "Mouse Inalámbrico - 32 unidades", 
    "Teclado Mecánico - 28 unidades",
    formato="numerado",
    generado_por="Sistema automático",
    categoria="Electrónicos",
    periodo="Último mes"
)

reporte2 = generar_reporte(
    "Inventario crítico",
    "Monitor 4K - Stock: 2",
    "Webcam HD - Stock: 1",
    "Parlantes - Stock: 3",
    formato="lista",
    separador="=",
    incluir_fecha=True,
    urgencia="Alta",
    accion_requerida="Reposición inmediata"
)

🔍 Introspección de funciones

Python te permite inspeccionar las máquinas que has creado:

def maquina_compleja(param1, param2="default", *args, param_clave, **kwargs):
    """Una máquina compleja para demostrar introspección"""
    pass

# Inspeccionar los parámetros de la función
import inspect

print("🔍 Análisis de la máquina:")
signature = inspect.signature(maquina_compleja)

for name, param in signature.parameters.items():
    print(f"⚙️ {name}:")
    print(f"   Tipo: {param.kind}")
    print(f"   Default: {param.default if param.default != param.empty else 'Sin default'}")
    
# Información adicional
print(f"\n📋 Documentación: {maquina_compleja.__doc__}")
print(f"🏷️ Nombre: {maquina_compleja.__name__}")

🎯 Comprueba tu comprensión

Ejercicio 1: Calculadora de envíos

Crea una función que calcule el costo de envío con múltiples opciones:

def calcular_envio(peso, distancia, tipo="normal", urgente=False, seguro=False, **extras):
    """
    Calcula el costo de envío con múltiples opciones.
    
    Args:
        peso: Peso en kg (obligatorio)
        distancia: Distancia en km (obligatorio)
        tipo: "normal", "express", "economico" (default: "normal")
        urgente: Si requiere entrega urgente (default: False)
        seguro: Si incluye seguro (default: False)
        **extras: Servicios adicionales
    """
    # Tu código aquí
    pass

# Pruebas
costo1 = calcular_envio(2.5, 100)
costo2 = calcular_envio(5.0, 200, tipo="express", urgente=True)
costo3 = calcular_envio(1.2, 50, seguro=True, embalaje_especial=25, manejo_fragil=15)

Ejercicio 2: Procesador de productos

Crea una función que procese una lista variable de productos:

def procesar_productos(*productos, descuento_global=0, **configuraciones):
    """
    Procesa múltiples productos con configuraciones flexibles.
    
    Args:
        *productos: Lista variable de diccionarios de productos
        descuento_global: Descuento aplicado a todos los productos
        **configuraciones: Configuraciones adicionales del procesamiento
    """
    # Tu código aquí
    pass

# Prueba
productos = [
    {"nombre": "Laptop", "precio": 1000, "categoria": "Electronica"},
    {"nombre": "Mouse", "precio": 30, "categoria": "Accesorios"}
]

resultado = procesar_productos(
    *productos,
    descuento_global=10,
    aplicar_impuesto=True,
    moneda="USD",
    incluir_garantia=True
)

Ejercicio 3: Validador flexible

Crea una función que valide datos con reglas variables:

def validar_datos(datos, *reglas_obligatorias, permitir_extras=False, **reglas_opcionales):
    """
    Valida un diccionario de datos contra reglas flexibles.
    
    Args:
        datos: Diccionario con datos a validar
        *reglas_obligatorias: Campos que deben existir
        permitir_extras: Si permite campos no especificados
        **reglas_opcionales: Validaciones opcionales por campo
    """
    # Tu código aquí
    pass

# Prueba
datos_usuario = {
    "nombre": "Ana García",
    "email": "ana@email.com",
    "edad": 25,
    "telefono": "555-0123"
}

es_valido = validar_datos(
    datos_usuario,
    "nombre", "email",  # campos obligatorios
    permitir_extras=True,
    edad_minima=18,
    email_formato=r".*@.*\..*"
)

💡 Mejores prácticas

  1. Orden consistente: Siempre sigue el orden estándar de parámetros
  2. Nombres descriptivos: Los parámetros deben explicar qué representan
  3. Valores por defecto sensatos: Usa defaults que tengan sentido en el contexto
  4. Documentación clara: Explica todos los parámetros en el docstring
  5. **No abuses de *args y kwargs: Úsalos cuando realmente aporten flexibilidad
  6. Validación de entrada: Verifica que los argumentos tengan sentido

🎉 ¡Felicitaciones!

Has aprendido a crear máquinas súper configurables para tu almacén digital. Ahora puedes:

  • ✅ Crear funciones flexibles con parámetros opcionales
  • ✅ Usar argumentos por palabra clave para mayor claridad
  • ✅ Implementar funciones que acepten cantidad variable de argumentos
  • ✅ Combinar diferentes tipos de parámetros eficientemente
  • ✅ Hacer tu código más reutilizable y mantenible

En la siguiente sección aprenderemos sobre valores de retorno: cómo hacer que nuestras máquinas nos entreguen exactamente lo que necesitamos.


🧭 Navegación: