Funciones

Argumentos variables: *args y **kwargs


En ocasiones, necesitamos definir funciones que acepten un número indefinido de argumentos. Python permite hacerlo mediante dos herramientas muy útiles: *args y **kwargs.

El problema: Supongamos que queremos definir una función que sume varios números. Si conocemos de antemano cuántos argumentos tendrá, podemos hacer lo siguiente:

def sumar(a, b, c):
    return a + b + c

print(sumar(1, 2, 3))  # 6

Pero si intentamos pasarle más argumentos:

print(sumar(1, 2, 3, 4))  # ❌ Error: demasiados argumentos

Como ves, esto no escala bien. La solución es usar *args.


Uso de *args:

*args permite a una función aceptar un número variable de argumentos posicionales.

def sumar(*args):
    resultado = 0
    for numero in args:
        resultado += numero
    return resultado

print(sumar(1, 2))           # 3
print(sumar(5, 10, 15, 20))  # 50

Internamente, args es una tupla que contiene todos los argumentos posicionales enviados

Versión más simple:

Ya que args es una tupla, podemos usar la función sum() directamente:

def sumar(*args):
    return sum(args)

Uso de **kwargs:

**kwargs permite pasar un número variable de argumentos con nombre (también llamados argumentos con palabra clave).

def imprimir_info(**kwargs):
    for clave, valor in kwargs.items():
        print(f"{clave}: {valor}")

imprimir_info(nombre="Ana", edad=25, ciudad="Madrid")

Internamente, kwargs es un diccionario donde:

  • Las claves son los nombres de los argumentos.
  • Los valores son los valores pasados.

Igual que con args, el nombre kwargs es una convención. Puedes usar otro nombre mientras empiece con **.


Combinando argumentos normales, *args y **kwargs:

Una función puede usar los tres tipos de argumentos, pero deben aparecer en este orden:

def funcion(a, b, *args, **kwargs):
    print("a:", a)
    print("b:", b)
    print("args:", args)
    print("kwargs:", kwargs)

funcion(1, 2, 3, 4, x=5, y=6)

Truco útil: Tuple unpacking

Puedes usar el operador * o ** al llamar una función para "desempaquetar" una tupla o diccionario:

def saludar(nombre, edad):
    print(f"Hola {nombre}, tienes {edad} años.")

# Tupla
datos = ("Luis", 30)
saludar(*datos)  # Equivale a saludar("Luis", 30)

# Diccionario
info = {"nombre": "María", "edad": 28}
saludar(**info)  # Equivale a saludar(nombre="María", edad=28)