
Passo 1 de 8
Reunir argumentos posicionais com *args
Aprenda a coletar argumentos posicionais adicionais em uma tupla e a processá-los, inclusive quando nenhum valor é fornecido.
Trilha de aprendizado · Nível 4 · Tutorial 4
Crie funções que aceitem uma quantidade variável de argumentos e use dados de sequências ou dicionários em chamadas.
Reunir argumentos posicionais com *args
Aprenda a coletar argumentos posicionais adicionais em uma tupla e a processá-los, inclusive quando nenhum valor é fornecido. 2 min
Reunir argumentos nomeados com **kwargs
Entenda como argumentos nomeados adicionais são reunidos em um dicionário e processe os dados coletados. 2 min
Combinar parâmetros explícitos e variáveis
Organize parâmetros comuns, coletores variáveis e opções somente nomeadas em uma assinatura, acompanhando o destino de cada argumento. 3 min
Expandir listas e tuplas com *
Use * em uma chamada para distribuir os elementos de uma lista ou tupla como argumentos posicionais separados. 2 min
Expandir dicionários com **
Use dicionários para fornecer argumentos nomeados e combine sua expansão com argumentos posicionais. 3 min
Evitar conflitos ao expandir argumentos
Identifique quando duas origens tentam preencher o mesmo parâmetro e corrija a chamada antes de executá-la novamente. 2 min
Escolher uma assinatura que comunique a intenção
Decida quais informações devem aparecer claramente na assinatura e quando coletores variáveis representam melhor os dados. 2 min
Aplicar: resumir um lote de valores
Implemente no seu computador uma função que combina parâmetros explícitos, argumentos variáveis e expansão de coleções. 4 min

Passo 1 de 8
Aprenda a coletar argumentos posicionais adicionais em uma tupla e a processá-los, inclusive quando nenhum valor é fornecido.
Um parâmetro precedido de * reúne todos os argumentos posicionais fornecidos na chamada. Dentro da função, esses valores formam uma tupla, na mesma ordem em que foram passados.
Em def registrar(*valores):, é o asterisco que produz esse comportamento. valores é apenas o nome escolhido para a tupla.

Na chamada registrar(8, 3, 5), os três argumentos tornam-se a tupla (8, 3, 5).
Como o parâmetro representa uma tupla, você pode percorrê-lo em um laço e consultar sua quantidade com len. A função abaixo aceita um, dois ou quantos valores posicionais forem necessários.
Execute chamadas com quantidades diferentes de números.
def resumir(*valores):
total = 0
for valor in valores:
total += valor
return len(valores), total
print(resumir(7))
print(resumir(7, 2, 4))Exemplo
A primeira chamada retorna (1, 7). A segunda retorna (3, 13): valores contém a tupla (7, 2, 4).
A função ainda pode ser chamada sem argumentos posicionais.
def somar(*numeros):
total = 0
for numero in numeros:
total += numero
return total
print(somar()) # 0
print(somar(10)) # 10
print(somar(10, 5)) # 15Dica
args é um nome convencional, mas não obrigatório. *numeros, *itens e *notas têm o mesmo comportamento e podem comunicar melhor o papel dos valores. Sem argumentos, o parâmetro recebe a tupla vazia (); por isso, o acumulador iniciado em zero produz um resultado coerente.
Complete o parâmetro para que a função aceite qualquer quantidade de argumentos posicionais:
def quantidade(_____): return len(valores)
Considere esta função:
def analisar(*numeros): total = 0 for numero in numeros: total += numero return len(numeros), total
O que retornam, respectivamente, analisar(), analisar(4) e analisar(4, 6, 3)?

Passo 2 de 8
Entenda como argumentos nomeados adicionais são reunidos em um dicionário e processe os dados coletados.
Na definição, um parâmetro precedido de ** reúne os argumentos nomeados adicionais em um dicionário. O nome de cada argumento vira uma chave textual, e o valor fornecido vira o valor associado.
def coletar(**metadados):
return metadados
resultado = coletar(cor="azul", prioridade=2)Nesse caso, metadados recebe {"cor": "azul", "prioridade": 2}.
A associação preserva cada nome usado na chamada como uma chave do dicionário recebido pela função.

Cada par nome=valor da chamada se torna uma entrada nome: valor no dicionário.
Dica
kwargs é apenas uma convenção. Os dois asteriscos determinam a coleta; você pode usar um nome descritivo, como metadados, opcoes ou detalhes.
Dentro da função, use operações de dicionários já conhecidas. É possível consultar uma chave com get, contar entradas com len ou percorrer os pares.
A função conta os argumentos recebidos e consulta a origem. Quando nenhum argumento é fornecido, metadados é um dicionário vazio.
def resumir_metadados(**metadados):
return {
"quantidade": len(metadados),
"origem": metadados.get("origem", "não informada"),
}
print(resumir_metadados(origem="site", campanha="inverno"))
print(resumir_metadados())
# Saídas esperadas:
# {'quantidade': 2, 'origem': 'site'}
# {'quantidade': 0, 'origem': 'não informada'}Associe cada elemento da definição ou da chamada ao resultado correspondente.
Toque em um item e depois no par correspondente.
Leia a função e acompanhe o dicionário recebido em cada chamada.
def totalizar(**valores):
total = 0
for valor in valores.values():
total += valor
return len(valores), total
resultado_a = totalizar(cafe=8, suco=6)
resultado_b = totalizar()Preveja os valores de resultado_a e resultado_b. Na resposta, descreva também o conteúdo recebido pelo parâmetro valores em cada chamada.
Escreva pelo menos 40 caracteres (0/40).

Passo 3 de 8
Organize parâmetros comuns, coletores variáveis e opções somente nomeadas em uma assinatura, acompanhando o destino de cada argumento.
Uma assinatura pode combinar parâmetros explícitos e variáveis. Antes de *pontos, os parâmetros comuns seguem a regra já conhecida: os obrigatórios vêm antes daqueles com valor padrão.
Em def registrar(nome, categoria="geral", *pontos, ativo=True, **dados):, os argumentos posicionais preenchem primeiro nome e categoria. Somente os posicionais que sobrarem serão reunidos na tupla pontos.
Observe o destino de cada parte da chamada.
def registrar(nome, categoria="geral", *pontos, ativo=True, **dados):
return {
"nome": nome,
"categoria": categoria,
"pontos": pontos,
"ativo": ativo,
"dados": dados,
}
resultado = registrar(
"Ana",
"jogo",
10,
20,
ativo=False,
equipe="Azul",
)
print(resultado)
# Resultado esperado:
# {'nome': 'Ana', 'categoria': 'jogo', 'pontos': (10, 20),
# 'ativo': False, 'dados': {'equipe': 'Azul'}}Na chamada, "Ana" e "jogo" são consumidos pelos parâmetros comuns nome e categoria. Os posicionais restantes, 10 e 20, formam pontos.
Como ativo foi declarado depois de *pontos, ele só pode ser fornecido por nome. O nome equipe não corresponde a um parâmetro explícito, então vai para dados. Já ativo não entra nesse dicionário, pois foi associado ao parâmetro explícito de mesmo nome.

Os parâmetros explícitos recebem seus valores antes dos coletores: nome recebe "Ana", categoria recebe "jogo", pontos recebe (10, 20), ativo recebe False e dados recebe {"equipe": "Azul"}.
Dica
Parâmetros declarados depois do coletor posicional, como ativo, são fornecidos somente por nome. Eles podem ser obrigatórios ou ter um valor padrão. Em ambos os casos, não são preenchidos por argumentos posicionais adicionais.
Uma assinatura admite no máximo um coletor de argumentos posicionais, escrito com *, e no máximo um coletor de argumentos nomeados, escrito com **.
O coletor com ** deve ficar no final da assinatura. Assim, a organização completa é: parâmetros comuns, coletor posicional, parâmetros somente nomeados e, por último, coletor nomeado.
Por exemplo, esta ordem é válida:def registrar(nome, categoria="geral", *pontos, ativo=True, **dados):
Organize os componentes dentro dos parênteses para formar uma assinatura válida.
Considere registrar("Ana", "jogo", 10, 20, ativo=False, equipe="Azul"). Associe cada parâmetro ao valor que ele recebe.
Toque em um item e depois no par correspondente.

Passo 4 de 8
Use * em uma chamada para distribuir os elementos de uma lista ou tupla como argumentos posicionais separados.
Na chamada, *sequencia fornece cada elemento de uma lista ou tupla como um argumento posicional separado, preservando a ordem.
Sem o asterisco, a coleção inteira é um único argumento. Com o asterisco, seus elementos ocupam posições consecutivas na chamada.
Imagine o * como um distribuidor: ele retira os elementos da sequência, na ordem, e os encaminha separadamente para a função.

Uma sequência com três elementos fornece três argumentos posicionais quando é expandida com *.
A primeira chamada entrega uma lista. A segunda entrega três valores separados.
def observar(*itens):
print(itens)
valores = [10, 20, 30]
observar(valores) # ([10, 20, 30],)
observar(*valores) # (10, 20, 30)Na definição, *valores coleta argumentos adicionais em uma tupla. Na chamada, *notas expande uma sequência em argumentos separados.
A expansão também funciona com funções de parâmetros fixos, desde que a quantidade de elementos corresponda aos parâmetros necessários.
Execute o código e compare as chamadas equivalentes.
def criar_ponto(x, y, z):
return (x, y, z)
coordenadas = [4, 7, 2]
print(criar_ponto(*coordenadas)) # (4, 7, 2)
def somar(*valores):
total = 0
for valor in valores:
total += valor
return total
notas = (8, 7, 9)
print(somar(*notas)) # 24
print(somar(*())) # 0Dica
Expandir uma sequência vazia fornece zero argumentos. Isso funciona em somar(*()) porque a função aceita não receber valores adicionais. Porém, a expansão vazia não preenche parâmetros obrigatórios: criar_ponto(*[]) ainda falha porque x, y e z não recebem valores.
Considere:
def exibir(primeiro, segundo, terceiro):
print(primeiro, segundo, terceiro)
itens = ("A", "B", "C")Qual chamada fornece corretamente os três elementos aos três parâmetros?
Complete a chamada para expandir vazia sem deixar de fornecer o parâmetro obrigatório nome:
def registrar(nome, *valores):
return nome, valores
vazia = []
resultado = registrar("lote", ___vazia)
# resultado: ("lote", ())
Passo 5 de 8
Use dicionários para fornecer argumentos nomeados e combine sua expansão com argumentos posicionais.
Na chamada, **dicionario expande cada entrada do dicionário como um argumento nomeado. As chaves se tornam os nomes dos argumentos, e os valores são associados aos parâmetros correspondentes.
Por isso, todas as chaves usadas nessa expansão precisam ser textos. A ordem escrita na assinatura determina os parâmetros disponíveis, mas a associação dos dados expandidos ocorre pelos nomes das chaves.
Na definição, **dados reúne argumentos nomeados em um dicionário. Na chamada, **opcoes distribui as entradas de um dicionário como argumentos nomeados separados.

A posição dos asteriscos muda o sentido: a definição reúne; a chamada distribui.
Usar ** na chamada não exige um coletor **kwargs na definição. A função pode ter apenas parâmetros comuns, desde que aceite todos os nomes fornecidos pelas chaves. Se o dicionário trouxer um nome que a assinatura não aceita, a chamada não poderá associá-lo.
Compare a chamada expandida com sua forma equivalente. O dicionário vazio não fornece nenhum argumento nomeado adicional.
def montar_etiqueta(produto, quantidade, cor="branca"):
return f"{produto}: {quantidade} unidade(s), cor {cor}"
opcoes = {"quantidade": 3, "cor": "azul"}
print(montar_etiqueta("caderno", **opcoes))
# Chamada equivalente:
print(montar_etiqueta("caderno", quantidade=3, cor="azul"))
sem_opcoes = {}
print(montar_etiqueta("caderno", 2, **sem_opcoes))
# Saídas esperadas:
# caderno: 3 unidade(s), cor azul
# caderno: 3 unidade(s), cor azul
# caderno: 2 unidade(s), cor brancaDica
Expandir {} fornece zero argumentos nomeados. Os argumentos obrigatórios ainda precisam vir de outra parte da chamada, enquanto parâmetros não fornecidos podem usar seus valores padrão.
Uma chamada pode combinar *sequencia e **dicionario. Os elementos da sequência fornecem os argumentos posicionais, na ordem, e as entradas do dicionário fornecem os argumentos nomeados. Na forma convencional, escreva a expansão posicional antes da expansão nomeada.
*posicionais fornece o nome e os pontos. Depois, **nomeados fornece ativo e o dado adicional equipe. O parâmetro ativo, declarado depois de *pontos, é associado pelo nome.
def registrar(nome, *pontos, ativo=True, **dados):
return {
"nome": nome,
"pontos": pontos,
"ativo": ativo,
"dados": dados,
}
posicionais = ["Ana", 10, 20]
nomeados = {"ativo": False, "equipe": "Azul"}
resultado = registrar(*posicionais, **nomeados)
print(resultado)
# Resultado esperado:
# {'nome': 'Ana', 'pontos': (10, 20),
# 'ativo': False, 'dados': {'equipe': 'Azul'}}Complete a chamada para expandir o dicionário nomeados:
resultado = registrar(*posicionais, _____nomeados)Um dicionário com uma chave numérica pode ser expandido com ** para fornecer argumentos nomeados.
Para usar **opcoes em uma chamada, a função precisa obrigatoriamente declarar um parâmetro **kwargs.

Passo 6 de 8
Identifique quando duas origens tentam preencher o mesmo parâmetro e corrija a chamada antes de executá-la novamente.
Cada parâmetro pode receber apenas um valor por chamada. No exemplo, *nomes fornece "Ana" para nome por posição, enquanto nome="Bia" tenta preencher o mesmo parâmetro por nome. O Python detecta o conflito, produz um TypeError e não inicia o corpo da função.
Execute este trecho separadamente para observar que a mensagem do corpo não aparece.
def apresentar(nome):
print("Corpo iniciado")
print(f"Olá, {nome}!")
nomes = ["Ana"]
apresentar(*nomes, nome="Bia")
# TypeError: o parâmetro 'nome' recebeu mais de um valorA duplicação é determinada pelo destino dos argumentos, e não pela forma visual como eles aparecem na chamada.

Se duas setas chegam ao mesmo parâmetro, a associação falha antes da execução do corpo.
A duplicação também ocorre quando um argumento nomeado explícito e um dicionário expandido usam a mesma chave. Da mesma forma, dois dicionários expandidos não podem fornecer o mesmo nome. O último valor não substitui o anterior: a chamada é rejeitada.
Execute cada chamada inválida separadamente, pois a primeira interrompe o script com TypeError.
def configurar(**opcoes):
print("Corpo iniciado")
print(opcoes)
base = {"tema": "escuro"}
# configurar(tema="claro", **base) # 'tema' aparece duas vezes
visual = {"tema": "claro", "fonte": 14}
acessibilidade = {"tema": "alto contraste"}
# configurar(**visual, **acessibilidade) # 'tema' aparece nos dois dicionários
# Correção: mantenha uma única origem para cada nome.
base["tema"] = "claro"
configurar(**base)
visual["tema"] = "alto contraste"
configurar(**visual)Atenção
**kwargs coleta nomes adicionais, mas não resolve duplicações. Se duas partes da chamada fornecem o mesmo nome, o conflito acontece antes que o dicionário de kwargs seja criado. Corrija removendo uma das origens ou reorganizando previamente os dados.
Considere o código:
def enviar(destino, **opcoes): print("Enviando")
dados = {"prioridade": "alta"}enviar("suporte", prioridade="baixa", **dados)
O que acontece?
Analise a chamada:
def resumo(titulo, *valores, **dados): return titulo, valores, dados
pos = ["Semana", 10, 20]extras = {"setor": "Norte", "titulo": "Duplicado"}resumo(*pos, **extras)
Quais são as duas origens do valor de titulo? Reescreva os dados ou a chamada para preservar "Semana", os valores 10 e 20 e o setor "Norte", sem duplicação.
Escreva pelo menos 40 caracteres (0/40).

Passo 7 de 8
Decida quais informações devem aparecer claramente na assinatura e quando coletores variáveis representam melhor os dados.
Use *args quando vários valores desempenham o mesmo papel e a quantidade pode variar. Use **kwargs quando o conjunto de informações nomeadas é intencionalmente aberto.
Dados obrigatórios e opções conhecidas devem, em geral, aparecer como parâmetros explícitos. Assim, quem lê a chamada consegue perceber o que a função espera.

À esquerda, coletores amplos escondem a função de cada entrada. À direita, dados essenciais ocupam posições claras e apenas as partes realmente variáveis seguem para coletores.
Exemplo
Assinatura excessivamente aberta:
def criar_usuario(**dados):
Ela não revela que nome e email são obrigatórios. Além disso, uma chamada como criar_usuario(nome="Ana", emial="ana@exemplo.com") pode coletar o erro de digitação sem acusar um nome desconhecido.
Assinatura que comunica melhor a intenção:
def criar_usuario(nome, email, tema="claro"):
Agora os requisitos e a opção conhecida estão visíveis. Já em def registrar_evento(evento, **detalhes):, o dicionário variável faz sentido se cada tipo de evento puder trazer detalhes diferentes.
Dica
Antes de adicionar um coletor, pergunte: “Todos esses valores têm o mesmo papel?” para *args e “Os nomes adicionais são realmente abertos?” para **kwargs. Se a resposta for não, prefira parâmetros explícitos.
Uma função deve receber obrigatoriamente o nome de um sensor, qualquer quantidade de leituras numéricas e uma unidade opcional fornecida por nome. Qual assinatura comunica melhor essa intenção?
Uma ocorrência exige um cliente, pode conter várias mensagens, tem prioridade opcional e pode receber campos de contexto diferentes conforme a integração. Proponha uma assinatura e justifique o que deve ser explícito ou variável.
Escreva pelo menos 40 caracteres (0/40).

Passo 8 de 8
Implemente no seu computador uma função que combina parâmetros explícitos, argumentos variáveis e expansão de coleções.
Você criará resumir_lote, com quatro partes: nome identifica obrigatoriamente o lote; *valores reúne os números; unidade é uma opção fornecida somente por nome; e **metadados recebe informações adicionais, como origem e responsável.

Os parâmetros explícitos destacam os dados essenciais; os coletores recebem apenas o que sobra.
Crie um arquivo chamado resumo_lotes.py no seu editor, copie o código completo abaixo e execute-o com Python 3. A função acumula os valores em um laço e devolve um dicionário com nome, quantidade, total, unidade e metadados.
def resumir_lote(nome, *valores, unidade="un.", **metadados):
total = 0
for valor in valores:
total += valor
return {
"nome": nome,
"quantidade": len(valores),
"total": total,
"unidade": unidade,
"metadados": metadados,
}
# Chamada direta
direto = resumir_lote(
"Lote A",
10,
15,
5,
unidade="kg",
origem="balança",
)
# Chamada equivalente com expansão
valores = [10, 15, 5]
opcoes = {"unidade": "kg", "origem": "balança"}
expandido = resumir_lote("Lote A", *valores, **opcoes)
# Chamada sem valores nem dados adicionais
vazio = resumir_lote("Lote vazio")
print(direto)
print(expandido)
print(direto == expandido)
print(vazio)
# Conflito: unidade seria fornecida duas vezes.
# Remova o comentário para observar o TypeError e depois restaure-o.
# resumir_lote("Lote B", *valores, unidade="g", **opcoes)Exemplo
A execução deve mostrar:
{'nome': 'Lote A', 'quantidade': 3, 'total': 30, 'unidade': 'kg', 'metadados': {'origem': 'balança'}}
{'nome': 'Lote A', 'quantidade': 3, 'total': 30, 'unidade': 'kg', 'metadados': {'origem': 'balança'}}
True
{'nome': 'Lote vazio', 'quantidade': 0, 'total': 0, 'unidade': 'un.', 'metadados': {}}
Compare os resultados direto e expandido. Explique por que são equivalentes, o que ocorre na chamada sem adicionais e por que a chamada comentada gera duplicação. Escreva uma versão corrigida dessa chamada e justifique por que nome e unidade são parâmetros explícitos.
Escreva pelo menos 120 caracteres (0/120).
Resumo
Os asteriscos cumprem sentidos complementares conforme o local em que aparecem.
*valores coleta argumentos posicionais adicionais em uma tupla e **metadados coleta argumentos nomeados adicionais em um dicionário.*sequencia distribui elementos como argumentos posicionais e **dicionario distribui entradas como argumentos nomeados.**kwargs não elimina duplicações.Parabéns! Você concluiu: Receber argumentos variáveis com *args e **kwargs
100 XP
Milhares de cursos online em vídeo, ebooks e áudiobooks.
Para testar seus conhecimentos no decorrer dos cursos online
Gerado diretamente na galeria de fotos do seu celular e enviado ao seu e-mail
Baixe nosso aplicativo pelo QR Code ou pelos links abaixo:.
+ de 10 milhões
de alunos
Certificado grátis e
válido em todo o Brasil
60 mil exercícios
gratuitos
4,8/5 classificação
nas lojas de apps
Cursos gratuitos em
vídeo, ebooks e audiobooks