Menu

*args y **kwargs en Python: argumentos posicionales y de palabra clave flexibles

Qué significan *args y **kwargs, cuándo usarlos y cómo reenviar argumentos entre funciones de forma limpia.

Cuando no sabes cuántos argumentos va a haber

La mayoría de las funciones toman un número fijo de parámetros. Pero a veces necesitas algo más flexible — un logger que acepte cualquier número de mensajes, una función envoltorio que reenvíe lo que reciba a otra función, una función de dibujado que acepte configuración sin saber exactamente qué opciones usará quien la llame.

Python resuelve esto con dos marcadores especiales en la lista de parámetros: *args y **kwargs.

*args recoge argumentos posicionales

Un solo asterisco dice "empaqueta cualquier argumento posicional adicional en una tupla":

main.py
Output
Click Run to see the output here.

Dentro de la función, args es una tupla normal. Puedes iterar sobre ella, indexarla, pasarla a len() o hacer slicing.

*args suele aparecer junto a parámetros con nombre:

main.py
Output
Click Run to see the output here.

first captura el primer argumento; *rest empaqueta todo lo demás en una tupla.

**kwargs recoge argumentos de palabra clave

Dos asteriscos hacen lo equivalente para argumentos de palabra clave, empaquetándolos en un dict:

main.py
Output
Click Run to see the output here.

Dentro de describe, kwargs es un dict normal. Las claves son los nombres de las palabras clave como cadenas.

Usarlos juntos

Puedes usar ambos en la misma función. La convención es *args antes de **kwargs:

main.py
Output
Click Run to see the output here.

El orden completo de los parámetros, desde el principio al final, es:

  1. Parámetros posicionales normales (obligatorios o con valores por defecto).
  2. *args.
  3. Parámetros solo por palabra clave (todo lo que venga después de *args debe pasarse por nombre).
  4. **kwargs.
main.py
Output
Click Run to see the output here.

title captura el primer argumento posicional. El resto de los posicionales van a tags. draft tiene que pasarse por palabra clave (viene después de *tags). Cualquier otro argumento por palabra clave aterriza en metadata.

Desempaquetar con * y ** en el sitio de la llamada

Los asteriscos también funcionan en sentido inverso — expandiendo una secuencia o dict hacia los argumentos de una llamada:

main.py
Output
Click Run to see the output here.

Esto resulta increíblemente útil para reenviar argumentos:

main.py
Output
Click Run to see the output here.

wrapped no necesita saber qué argumentos espera log. Simplemente recoge todo y lo reenvía. Este patrón aparece constantemente en decoradores (un tema más avanzado) y en funciones envoltorio.

Cuando *args y **kwargs son la elección equivocada

Es fácil emocionarse de más y usarlos en todas partes. Dos advertencias:

Ocultan lo que una función espera

Si cada función en tu código es def f(*args, **kwargs), quien llama no tiene idea de qué argumentos son válidos. Usa parámetros con nombre siempre que puedas, y deja que *args/**kwargs transporten solo entradas genuinamente variádicas o reenvío puro.

Los mensajes de error se vuelven imprecisos

Un nombre de palabra clave mal escrito se convierte en un None silencioso o en un KeyError dentro de la función, en lugar de un "unexpected keyword argument" inmediato en el sitio de la llamada. Los parámetros con nombre te dan mucho mejor feedback.

Como regla: prefiere parámetros con nombre por defecto, y recurre a *args/**kwargs solo cuando la función es genuinamente flexible o está reenviando argumentos a otro callable.

Un pequeño ejemplo práctico

Un helper de estilo plotting que envuelve una función de terceros con algunos valores por defecto:

main.py
Output
Click Run to see the output here.

*values permite a quien llama pasar cualquier número de elementos; **style absorbe configuración adicional sin requerir que cada opción sea un parámetro con nombre. Es flexible sin ser opaco, porque la lógica interna te dice exactamente qué claves lee de style.

Recapitulación

  • *args empaqueta argumentos posicionales adicionales en una tupla.
  • **kwargs empaqueta argumentos por palabra clave adicionales en un dict.
  • En el sitio de la llamada, *seq y **dict desempaquetan en sentido contrario.
  • Los parámetros deben aparecer en este orden: normales → *args → solo por palabra clave → **kwargs.
  • No abuses — los parámetros con nombre son más claros cuando puedes usarlos.

Lo siguiente: lambda, una forma de escribir funciones pequeñas y desechables en línea.

Preguntas frecuentes

¿Qué es *args en Python?

*args recoge cualquier argumento posicional adicional en una tupla. def f(*args): te permite llamar a f(1, 2, 3) y recibir args como (1, 2, 3). El nombre args es una convención — podrías llamarlo como quieras, pero *args es lo que todo el mundo usa.

¿Qué es **kwargs en Python?

**kwargs recoge cualquier argumento de palabra clave adicional en un dict. def f(**kwargs): te permite llamar a f(name='Ada', age=30) y recibir kwargs como {'name': 'Ada', 'age': 30}. Juntos, *args y **kwargs permiten que una función acepte cualquier combinación de argumentos.

¿Hay que llamarlos args y kwargs?

No, lo que importa son los asteriscos, no los nombres. *values y **options funcionan igual. Pero args y kwargs son una convención casi universal en código Python — úsalos salvo que tengas una razón concreta para elegir algo más descriptivo.

Aprende a programar con Coddy

COMENZAR