Argumentos nomeados, valor padrão e escopo
Uma função com muitos parâmetros fica confusa de chamar só na ordem. E toda variável criada dentro de uma função vive e morre ali dentro, a menos que você diga o contrário.
Estudar esta lição interativa →Uma função com quatro ou cinco parâmetros fica arriscada de chamar só pela ordem: é fácil trocar a posição de dois argumentos por engano e não perceber, principalmente se os dois forem do mesmo tipo. Python resolve isso permitindo chamar uma função nomeando os parâmetros na própria chamada, em qualquer ordem:
def apresentar(nome, idade, cidade):
print(f"{nome}, {idade} anos, mora em {cidade}.")
apresentar("Ana", 30, "Recife")
apresentar(idade=30, cidade="Recife", nome="Ana")As duas chamadas produzem exatamente o mesmo resultado.
Além disso, um parâmetro pode ter um valor padrão, tornando-o opcional na chamada: se quem chama não passar aquele argumento, o valor combinado é usado automaticamente.
def saudar(nome, saudacao="Olá"):
print(f"{saudacao}, {nome}!")
saudar("Bruno")
saudar("Carla", saudacao="Boa tarde")Pense num pedido de café: "um café, por favor" já vem com açúcar padrão, a menos que você diga "sem açúcar". O parâmetro com valor padrão funciona assim: você só precisa mencionar o que for diferente do combinado.
Agora um conceito importante: toda variável criada dentro de uma função é local a ela, existe só enquanto a função está rodando e desaparece assim que ela termina. Uma variável criada fora de qualquer função, no corpo principal do programa, é global, e pode ser lida de dentro de qualquer função, sem restrição.
total_geral = 0
def mostrar_total():
print(f"O total geral é {total_geral}")
total_geral = 150
mostrar_total()total_geral (global) é lida dentro da função sem problema.
Ler o valor de uma variável global de dentro de uma função funciona sem nenhuma preparação extra. Mas se você tentar reatribuir (mudar) uma global de dentro de uma função, o Python assume, por padrão, que você quer criar uma variável local nova com o mesmo nome, o que costuma gerar confusão. Para modificar uma global de verdade, é preciso declarar isso explicitamente com global nome_da_variavel logo no início da função. Na prática, prefira passar o valor por parâmetro e devolver o resultado com return: o código fica mais fácil de ler e de testar.
Se dentro de uma função você usa uma variável antes de atribuir um valor a ela, mas em algum lugar mais abaixo, na mesma função, existe uma atribuição para esse mesmo nome, o Python já trata essa variável como local desde o início da função, mesmo antes da linha de atribuição. Isso gera UnboundLocalError: cannot access local variable 'saldo' where it is not associated with a value. É um dos erros mais confusos para quem está começando. O melhor antídoto não é global: é receber o valor como parâmetro e devolver o novo valor com return, como no exemplo abaixo. Declarar global saldo como primeira linha da função também funciona, mas esconde de onde o dado vem e deixa a função difícil de testar, então fica como último recurso.
saldo = 100
def sacar_errado(valor):
try:
saldo = saldo - valor # esse "saldo =" torna saldo LOCAL: ele é lido antes de existir
except UnboundLocalError as erro:
print("Erro:", erro)
sacar_errado(30)
# O jeito honesto: receber o valor e devolver o novo saldo, sem mexer em global
def sacar(saldo_atual, valor):
return saldo_atual - valor
saldo = sacar(saldo, 30)
print(saldo) # 70O primeiro bloco mostra o UnboundLocalError (capturado para a célula continuar); o segundo, o jeito sem global.
Um valor padrão é criado uma única vez, quando a função é definida, e não a cada chamada. Com um valor imutável (um número, um texto, None) isso não incomoda. Com um valor mutável, como lista=[], a mesma lista é reaproveitada em todas as chamadas, e os itens se acumulam entre elas. O padrão correto é usar None como valor padrão e criar a lista dentro da função:
def adicionar(item, lista=[]):
lista.append(item)
return lista
print(adicionar("a")) # ['a']
print(adicionar("b")) # ['a', 'b'] (surpresa: a lista padrão nasce UMA vez e é reaproveitada)
def adicionar_certo(item, lista=None):
if lista is None:
lista = [] # cria uma lista nova a CADA chamada
lista.append(item)
return lista
print(adicionar_certo("a")) # ['a']
print(adicionar_certo("b")) # ['b']Compare a segunda saída de cada função.
def criar_perfil(nome, ativo=True):
print(f"{nome} — ativo: {ativo}")
criar_perfil("Marina")Chame a função com argumento nomeado, sem passar ativo.
calcular_frete(peso_kg, expresso=False): o frete normal custa peso_kg * 2; se expresso for True, o valor final dobra. calcular_frete(5) deve devolver 10, e calcular_frete(5, expresso=True) deve devolver 20.def calcular_frete(peso_kg, expresso=False):
# calcule o frete normal (peso_kg * 2) e dobre se expresso for True
pass
🧩 Este é um exercício com correção automática — abra no app para completá-lo e verificar.