Módulo 3 - Funções avançadas

*args e **kwargs: quantidade variável

11 min de leitura · por Cesar Gargiulo, revisado pela equipe ValorFinal e GuardiaSec · Atualizado em 01/07/2026

O que você vai aprender

  • Usar *args para receber vários argumentos posicionais em uma tupla.
  • Usar **kwargs para receber vários argumentos nomeados em um dicionário.
  • Combinar parâmetros normais, *args e **kwargs na ordem correta.
  • Reconhecer quando uma função variável ajuda e quando complica.

Quando você não sabe quantos vêm

Até aqui, toda função tinha um número fixo de parâmetros. Mas pense na função print: ela aceita um valor, dois, dez, quantos você quiser. Como isso é possível? Com *args. Um parâmetro escrito com um asterisco recolhe todos os argumentos posicionais que sobrarem e os entrega dentro da função como uma tupla. Assim a função não precisa saber, de antemão, quantos valores vai receber. Ela lida com o que chegar.

def somar(*args):
    total = 0
    for numero in args:
        total += numero
    return total

print(somar(2, 3))          # 5
print(somar(2, 3, 4, 5))    # 14
print(somar())              # 0
print(type(somar.__name__)) # <class 'str'>

args é uma tupla com todos os posicionais que chegaram, de zero a muitos.

Dentro de somar, args é uma tupla comum: dá para percorrer com um laço, medir com len, indexar. A mesma função somou dois números, quatro números e até nenhum, devolvendo zero. Esse é o ponto de *args: uma única definição atende a chamadas de tamanhos diferentes. Vale reforçar que o nome args é só tradição da comunidade; você poderia escrever *numeros e funcionaria igual. O asterisco é que carrega o significado.

**kwargs: nomeados em quantidade variável

Assim como *args recolhe posicionais, **kwargs recolhe argumentos nomeados extras, e os entrega como um dicionário. A chave é o nome que você usou na chamada; o valor é o que você passou. Isso é ótimo para funções que aceitam opções variadas sem listar cada uma como parâmetro. Um bom exemplo é montar uma configuração ou um perfil em que os campos mudam de caso para caso.

def criar_perfil(nome, **kwargs):
    perfil = {"nome": nome}
    for chave, valor in kwargs.items():
        perfil[chave] = valor
    return perfil

print(criar_perfil("Ana", cidade="Recife", idade=30))
# {'nome': 'Ana', 'cidade': 'Recife', 'idade': 30}

print(criar_perfil("Bruno"))
# {'nome': 'Bruno'}

kwargs é um dicionário: cada argumento nomeado extra vira uma chave e um valor.

A ordem na definição precisa ser respeitada: primeiro os parâmetros normais (com ou sem padrão), depois *args, e por último **kwargs. Essa sequência não é arbitrária. O Python precisa saber onde param os valores fixos, onde começam os posicionais extras e onde entram os nomeados extras. Inverter a ordem gera erro de sintaxe. Guardando a sequência normal, *args, **kwargs, você monta funções bem flexíveis sem confundir o interpretador.

def registrar(evento, *args, **kwargs):
    print("evento:", evento)
    print("extras posicionais:", args)
    print("extras nomeados:", kwargs)

registrar("login", "10:05", "ok", usuario="ana", ip="1.2.3.4")
# evento: login
# extras posicionais: ('10:05', 'ok')
# extras nomeados: {'usuario': 'ana', 'ip': '1.2.3.4'}

Parâmetro normal, depois *args (tupla), depois **kwargs (dicionário).

Fixando *args e **kwargs

Vale usar *args e **kwargs com parcimônia. Eles brilham quando a função é genuinamente aberta, como uma que registra eventos ou repassa opções para outra função. Mas, quando os argumentos são conhecidos, parâmetros nomeados explícitos deixam a função mais clara e mais fácil de usar corretamente, porque o editor e a documentação mostram o que ela espera. Na dúvida, prefira nomes explícitos; recorra a *args e **kwargs quando a variação for real.

Teste rápido

Dentro de uma função, o que é o parâmetro *args?

Perguntas frequentes

Preciso chamar de args e kwargs mesmo?
Não. Os nomes args e kwargs são só convenção, e a comunidade os usa por hábito. O que faz o recurso funcionar é o asterisco (um para posicionais, dois para nomeados). Você poderia escrever *valores e **opcoes, mas manter args e kwargs ajuda outras pessoas a reconhecerem o padrão de imediato.
Posso ter parâmetros normais junto com *args e **kwargs?
Pode, e é o mais comum. A ordem na definição é: parâmetros normais primeiro, depois *args, por último **kwargs. Por exemplo, def registrar(evento, *args, **kwargs). Inverter essa ordem causa erro de sintaxe, porque o Python precisa saber onde cada grupo começa.
O que acontece se eu não passar nenhum argumento extra?
args fica sendo uma tupla vazia e kwargs um dicionário vazio. A função roda normalmente; o laço que percorre args simplesmente não itera nenhuma vez. Por isso somar() sem argumentos devolve zero, e criar_perfil só com o nome retorna apenas o nome.
Dá para usar o asterisco também na hora de chamar a função?
Dá, e é o caminho inverso, chamado desempacotamento. Se você tem uma lista numeros = [2, 3, 4], pode chamar somar(*numeros) e o Python espalha os itens como argumentos posicionais. Com dicionários, **config espalha os pares como argumentos nomeados. É muito usado para repassar argumentos entre funções.
Quando é melhor evitar *args e **kwargs?
Quando os argumentos são conhecidos e poucos. Nesses casos, parâmetros explícitos deixam claro o que a função espera, e o editor consegue avisar sobre erros. *args e **kwargs escondem a assinatura real, então use quando a variação for verdadeira, como funções que repassam opções ou registram eventos diversos.
Qual a diferença de um asterisco para dois asteriscos?
Um asterisco (*args) trata argumentos posicionais e os junta em uma tupla. Dois asteriscos (**kwargs) tratam argumentos nomeados e os juntam em um dicionário. É a mesma lógica das duas formas de chamar uma função, posicional e nomeada, aplicada ao recebimento em quantidade variável.

Fontes

Seu progresso fica salvo neste aparelho. Assinantes sincronizam entre os aparelhos.