W3docs

Python *args y **kwargs

Aprende cómo *args y **kwargs permiten que las funciones de Python acepten cualquier número de argumentos posicionales y de palabra clave, con ejemplos reales.

*args y **kwargs son sintaxis especiales en Python que permiten a una función aceptar un número variable de argumentos. *args recoge los argumentos posicionales adicionales en una tupla, mientras que **kwargs recoge los argumentos de palabra clave adicionales en un diccionario. Juntos ofrecen total flexibilidad: puedes escribir funciones que funcionen con uno o cien argumentos.

Esta página cubre ambas características en profundidad: cómo funcionan, cuándo usarlas, cómo combinarlas y los errores comunes que debes evitar.

¿Qué es *args?

Cuando antepones un asterisco simple (*) al nombre de un parámetro, Python recoge todos los argumentos posicionales adicionales pasados a la función en una tupla enlazada a ese nombre de parámetro. El nombre args es una convención — podrías escribir *numbers o *values — pero *args es universalmente comprendido.

def add_all(*args):
    total = 0
    for n in args:
        total += n
    return total

print(add_all(1, 2, 3))         # 6
print(add_all(10, 20, 30, 40))  # 100
print(add_all())                 # 0

Dentro de la función, args es una tupla ordinaria que puedes recorrer, indexar o pasar a otras funciones. Llamar a add_all() con cero argumentos es válido — args es simplemente una tupla vacía.

Combinar parámetros regulares con *args

Los parámetros regulares (posicionales) van primero; *args captura todo lo que sigue:

def greet(greeting, *names):
    for name in names:
        print(greeting + ', ' + name + '!')

greet('Hello', 'Alice', 'Bob', 'Charlie')
# Hello, Alice!
# Hello, Bob!
# Hello, Charlie!

greeting se rellena con el primer argumento; names recibe el resto como una tupla. Si llamas a greet('Hi') sin nombres adicionales, names es una tupla vacía y el bucle simplemente no se ejecuta — sin error.

¿Qué es **kwargs?

Dos asteriscos (**) antes del nombre de un parámetro le indican a Python que recoja todos los argumentos de palabra clave adicionales en un diccionario. Nuevamente, kwargs es una convención; cualquier identificador Python válido funciona.

def describe(**kwargs):
    for key, value in kwargs.items():
        print(key + ': ' + str(value))

describe(name='Alice', age=30, city='New York')
# name: Alice
# age: 30
# city: New York

Dentro de la función, kwargs es un diccionario ordinario. Puedes recorrerlo, buscar claves o pasarlo. El llamador decide qué claves proporcionar — ninguna está fijada por la definición de la función.

Cuándo usar **kwargs

**kwargs destaca cuando:

  • Una función necesita aceptar un conjunto flexible y abierto de opciones con nombre (configuración, metadatos, atributos HTML).
  • Estás escribiendo un envoltorio que debe reenviar argumentos de palabra clave a otra función sin saber cuáles son.
  • Quieres construir un diccionario a partir de argumentos de palabra clave de forma legible (evita el código repetitivo de dict(key=value, ...)).

Combinar *args y **kwargs

Una sola función puede aceptar argumentos posicionales ilimitados y argumentos de palabra clave ilimitados. El orden requerido en la firma es:

  1. Parámetros posicionales normales
  2. *args
  3. Parámetros de solo palabra clave (con valores por defecto)
  4. **kwargs
def log_event(event, *tags, **metadata):
    print('Event:', event)
    print('Tags:', tags)
    print('Metadata:', metadata)

log_event('login', 'auth', 'user', user_id=42, ip='127.0.0.1')
# Event: login
# Tags: ('auth', 'user')
# Metadata: {'user_id': 42, 'ip': '127.0.0.1'}

event toma el primer argumento posicional; tags captura los argumentos posicionales restantes; metadata captura todos los argumentos de palabra clave.

Desempaquetar argumentos con * y **

Los operadores * y ** no son solo para definiciones de funciones — también funcionan en el lado de la llamada para desempaquetar secuencias y mapeos en argumentos separados.

Desempaquetar una lista o tupla con *

def multiply(a, b, c):
    return a * b * c

nums = [2, 3, 4]
print(multiply(*nums))  # 24

*nums desempaqueta la lista de modo que a=2, b=3, c=4. Esto es equivalente a escribir multiply(2, 3, 4). Consulta Desempaquetar tuplas para más información sobre el operador de desempaquetado.

Desempaquetar un diccionario con **

def power(base, exp):
    return base ** exp

params = {'base': 3, 'exp': 4}
print(power(**params))  # 81

**params asigna cada clave del diccionario al nombre de parámetro correspondiente. Esto es útil cuando los argumentos se almacenan en un diccionario de configuración construido en tiempo de ejecución.

Argumentos de solo palabra clave después de *args

Cualquier parámetro listado después de *args en la firma solo puede pasarse por nombre (se convierte en un argumento de solo palabra clave). Esta es una forma limpia de agregar indicadores opcionales sin ambigüedad:

def configure(host, *args, port=80, debug=False):
    print('host:', host)
    print('extra:', args)
    print('port:', port)
    print('debug:', debug)

configure('localhost', 'arg1', port=8080, debug=True)
# host: localhost
# extra: ('arg1',)
# port: 8080
# debug: True

port y debug no pueden establecerse de forma posicional porque *args ya consume todo el desbordamiento posicional. Este patrón es común en las API de bibliotecas — los usuarios deben escribir port=8080 explícitamente, lo que hace que los sitios de llamada sean autodocumentados.

Para una explicación detallada de las reglas de ámbito de Python, consulta Ámbito en Python.

Reenviar argumentos a otra función

Uno de los usos más prácticos de *args/**kwargs es escribir envoltorios y decoradores que pasen argumentos a una función interna sin saber cuáles son esos argumentos:

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

def wrapper(*args, **kwargs):
    print('Calling with args:', args, 'kwargs:', kwargs)
    return add_all(*args)

print(wrapper(1, 2, 3))
# Calling with args: (1, 2, 3) kwargs: {}
# 6

Este patrón aparece en toda la biblioteca estándar de Python y es la base de los decoradores y las funciones de orden superior.

Orden completo de la firma

Python impone una regla de ordenamiento estricta para todos los tipos de parámetros. El orden completo es:

PosiciónTipoEjemplo
1Solo posicional (Python 3.8+)a, b, /
2Posicional o de palabra clave normalx, y
3Posicional variable*args
4Solo palabra claveflag=True
5Palabra clave variable**kwargs

Romper este orden produce un SyntaxError. Una función que usa los cinco tipos se ve así:

def full_sig(pos1, pos2, /, normal, *args, kw_only, **kwargs):
    print(pos1, pos2, normal, args, kw_only, kwargs)

full_sig(1, 2, 3, 4, 5, kw_only='k', extra='e')
# 1 2 3 (4, 5) k {'extra': 'e'}

En el código cotidiano raramente necesitas los cinco a la vez. Los patrones más comunes son *args solo, **kwargs solo, o *args seguido de **kwargs.

Anotaciones de tipo

Puedes anotar *args y **kwargs con sugerencias de tipo. La anotación se aplica a cada elemento individual, no a la tupla o diccionario en sí:

from typing import Any

def add_all(*args: float) -> float:
    return sum(args)

def describe(**kwargs: Any) -> None:
    for key, value in kwargs.items():
        print(f'{key}: {value}')

print(add_all(1.5, 2.5, 3.0))  # 7.0
describe(name='Bob', score=99)
# name: Bob
# score: 99

*args: float significa que se espera que cada elemento de args sea un float. **kwargs: Any significa que los valores pueden ser cualquier cosa. Esto mantiene satisfechas a las herramientas de análisis estático mientras se preserva la flexibilidad en tiempo de ejecución.

Errores comunes

1. Orden incorrecto de argumentos en la firma

Poner **kwargs antes de *args es un SyntaxError:

# Wrong — raises SyntaxError
# def bad(name, **kwargs, *args): ...

# Correct
def good(name, *args, **kwargs):
    pass

2. Mutar la tupla args

args es una tupla y por lo tanto es inmutable. Si necesitas modificar los argumentos, conviértelos primero a una lista:

def double_all(*args):
    items = list(args)      # mutable copy
    items = [x * 2 for x in items]
    return items

print(double_all(1, 2, 3))  # [2, 4, 6]

3. Sombrear el nombre de un parámetro requerido

Si usas *args y también tienes un argumento de palabra clave con el mismo nombre que un parámetro posicional, los llamadores pueden confundirse. Mantén los nombres de parámetros distintos y usa parámetros de solo palabra clave (después de *args) para los indicadores opcionales.

4. Abusar de **kwargs en lugar de parámetros explícitos

**kwargs oculta lo que una función realmente acepta, dificultando el autocompletado y el análisis estático. Prefiere parámetros explícitos para las opciones que tu función genuinamente admite; usa **kwargs solo cuando el conjunto de opciones es verdaderamente abierto o cuando reenvías a otra función.

Resumen

CaracterísticaSintaxisQué recogeTipo dentro de la función
Args posicionales variables*argsArgumentos posicionales adicionalestuple
Args de palabra clave variables**kwargsArgumentos de palabra clave adicionalesdict
Desempaquetar secuencia en la llamadafunc(*seq)Lista/tupla → args posicionales
Desempaquetar mapeo en la llamadafunc(**mapping)Dict → args de palabra clave

Para temas estrechamente relacionados, consulta Funciones de Python para los conceptos básicos de funciones, Python Lambda para funciones anónimas, y Ámbito en Python para cómo Python resuelve los nombres de variables.

Práctica

Práctica
In Python, what does *args do when used in a function definition?
In Python, what does *args do when used in a function definition?
Was this page helpful?