Python *args e **kwargs
Aprenda como *args e **kwargs permitem que funções Python aceitem qualquer número de argumentos posicionais e nomeados, com exemplos reais e padrões comuns.
*args e **kwargs são sintaxes especiais em Python que permitem que uma função aceite um número variável de argumentos. *args coleta argumentos posicionais extras em uma tupla, enquanto **kwargs coleta argumentos nomeados extras em um dicionário. Juntos, oferecem total flexibilidade — você pode escrever funções que funcionam com um argumento ou com cem.
Esta página aborda ambos os recursos em profundidade: como funcionam, quando usá-los, como combiná-los e as armadilhas comuns a evitar.
O que é *args?
Quando você prefixa o nome de um parâmetro com um único asterisco (*), Python coleta todos os argumentos posicionais extras passados para a função em uma tupla vinculada a esse nome de parâmetro. O nome args é uma convenção — você poderia escrever *numbers ou *values — mas *args é universalmente compreendido.
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()) # 0Dentro da função, args é uma tupla comum que você pode percorrer, indexar ou passar para outras funções. Chamar add_all() com zero argumentos é válido — args é simplesmente uma tupla vazia.
Combinando parâmetros regulares com *args
Parâmetros regulares (posicionais) vêm primeiro; *args captura tudo que vem depois:
def greet(greeting, *names):
for name in names:
print(greeting + ', ' + name + '!')
greet('Hello', 'Alice', 'Bob', 'Charlie')
# Hello, Alice!
# Hello, Bob!
# Hello, Charlie!greeting é preenchido pelo primeiro argumento; names recebe o restante como uma tupla. Se você chamar greet('Hi') sem nomes extras, names é uma tupla vazia e o laço simplesmente não é executado — sem erro.
O que é **kwargs?
Dois asteriscos (**) antes de um nome de parâmetro dizem ao Python para coletar todos os argumentos nomeados extras em um dicionário. Novamente, kwargs é uma convenção; qualquer 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 YorkDentro da função, kwargs é um dicionário comum. Você pode percorrê-lo, buscar chaves ou passá-lo adiante. O chamador decide quais chaves fornecer — nenhuma delas é fixada pela definição da função.
Quando usar **kwargs
**kwargs é ideal quando:
- Uma função precisa aceitar um conjunto flexível e aberto de opções nomeadas (configuração, metadados, atributos HTML).
- Você está escrevendo um wrapper que deve encaminhar argumentos nomeados para outra função sem saber quais são.
- Você quer construir um dicionário a partir de argumentos nomeados de forma legível (evita o boilerplate de
dict(key=value, ...)).
Combinando *args e **kwargs
Uma única função pode aceitar argumentos posicionais ilimitados e argumentos nomeados ilimitados. A ordem obrigatória na assinatura é:
- Parâmetros posicionais normais
*args- Parâmetros somente por nome (com padrões)
**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 recebe o primeiro argumento posicional; tags captura os argumentos posicionais restantes; metadata captura todos os argumentos nomeados.
Desempacotando Argumentos com * e **
Os operadores * e ** não servem apenas para definições de funções — eles também funcionam no lado da chamada para desempacotar sequências e mapeamentos em argumentos separados.
Desempacotando uma lista ou tupla com *
def multiply(a, b, c):
return a * b * c
nums = [2, 3, 4]
print(multiply(*nums)) # 24*nums desempacota a lista para que a=2, b=3, c=4. Isso é equivalente a escrever multiply(2, 3, 4). Veja Desempacotar Tuplas para mais informações sobre o operador de desempacotamento.
Desempacotando um dicionário com **
def power(base, exp):
return base ** exp
params = {'base': 3, 'exp': 4}
print(power(**params)) # 81**params mapeia cada chave do dicionário para o nome de parâmetro correspondente. Isso é útil quando os argumentos são armazenados em um dicionário de configuração construído em tempo de execução.
Argumentos Somente por Nome Após *args
Qualquer parâmetro listado após *args na assinatura só pode ser passado por nome (torna-se um argumento somente por nome). Esta é uma forma limpa de adicionar sinalizadores opcionais sem ambiguidade:
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: Trueport e debug não podem ser definidos posicionalmente porque *args já consome todo o excesso posicional. Esse padrão é comum em APIs de bibliotecas — os usuários devem escrever port=8080 explicitamente, o que torna os pontos de chamada autodocumentados.
Para uma explicação detalhada das regras de escopo do Python, consulte Python Scope.
Encaminhando Argumentos para Outra Função
Um dos usos mais práticos de *args/**kwargs é escrever wrappers e decorators que passam argumentos para uma função interna sem saber quais são esses 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: {}
# 6Esse padrão aparece em toda a biblioteca padrão do Python e é a base dos decorators e funções de ordem superior.
Ordem Completa da Assinatura
Python impõe uma regra de ordenação estrita para todos os tipos de parâmetros. A ordem completa é:
| Posição | Tipo | Exemplo |
|---|---|---|
| 1 | Somente posicional (Python 3.8+) | a, b, / |
| 2 | Posicional ou por nome normal | x, y |
| 3 | Posicional variável | *args |
| 4 | Somente por nome | flag=True |
| 5 | Por nome variável | **kwargs |
Quebrar essa ordem é um SyntaxError. Uma função que usa todos os cinco tipos se parece com:
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'}No código cotidiano, raramente você precisa de todos os cinco ao mesmo tempo. Os padrões mais comuns são *args sozinho, **kwargs sozinho, ou *args seguido de **kwargs.
Anotações de Tipo
Você pode anotar *args e **kwargs com dicas de tipo. A anotação se aplica a cada item individual, não à tupla ou ao dicionário em si:
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 cada elemento de args deve ser um float. **kwargs: Any significa que os valores podem ser qualquer coisa. Isso mantém as ferramentas de análise estática satisfeitas enquanto preserva a flexibilidade em tempo de execução.
Armadilhas Comuns
1. Ordem errada dos argumentos na assinatura
Colocar **kwargs antes de *args é um SyntaxError:
# Wrong — raises SyntaxError
# def bad(name, **kwargs, *args): ...
# Correct
def good(name, *args, **kwargs):
pass2. Mutando a tupla args
args é uma tupla e, portanto, imutável. Se precisar modificar os argumentos, converta para uma lista primeiro:
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. Sombreando o nome de um parâmetro obrigatório
Se você usa *args e também tem um argumento nomeado com o mesmo nome que um parâmetro posicional, os chamadores podem ficar confusos. Mantenha os nomes dos parâmetros distintos e use parâmetros somente por nome (após *args) para sinalizadores opcionais.
4. Usar **kwargs em excesso em vez de parâmetros explícitos
**kwargs oculta o que uma função realmente aceita, dificultando o autocompletar e a análise estática. Prefira parâmetros explícitos para as opções que sua função genuinamente suporta; use **kwargs somente quando o conjunto de opções for verdadeiramente aberto ou ao encaminhar para outra função.
Resumo
| Recurso | Sintaxe | O que coleta | Tipo dentro da função |
|---|---|---|---|
| Args posicionais variáveis | *args | Argumentos posicionais extras | tuple |
| Args nomeados variáveis | **kwargs | Argumentos nomeados extras | dict |
| Desempacotar sequência na chamada | func(*seq) | Lista/tupla → args posicionais | — |
| Desempacotar mapeamento na chamada | func(**mapping) | Dict → args nomeados | — |
Para tópicos relacionados, veja Python Functions para conceitos básicos de funções, Python Lambda para funções anônimas e Python Scope para como Python resolve nomes de variáveis.