Você já enfrentou resultados inesperados ao usar listas ou dicionários como valores padrão em funções Python? Esse é um problema comum que pode causar bugs sutis e difíceis de encontrar. Neste artigo técnico, vamos desmistificar o motivo desse comportamento, mostrando exemplos práticos e como evitá-lo com boas práticas de programação. Se você é um desenvolvedor Python buscando produzir código mais robusto e previsível, este conteúdo é essencial para o seu dia a dia.
Evitando Surpresas
Ao definir funções em Python, usar valores padrão em argumentos é comum para facilitar chamadas. Contudo, quando o valor padrão é um tipo mutável, como listas ou dicionários, isso pode causar efeitos inesperados. Vamos analisar exemplos para entender esse comportamento.
Exemplo Problemático: Lista Mutável como Valor Padrão
| |
Aqui, o segundo print adiciona o item ‘banana’ à mesma lista usada na primeira chamada, porque o objeto lista padrão foi criado uma vez e reutilizado. Isso acontece porque argumentos padrão são avaliados apenas na definição da função.
Corrigindo com None como Valor Padrão
A forma recomendada é usar None e criar a lista dentro da função quando necessário:
| |
Assim, cada chamada sem lista passa a criar uma nova lista vazia, evitando efeitos colaterais.
Mais um Exemplo com Dicionário Mutável
| |
No caso acima, o dicionário padrão é compartilhado e mantido entre as chamadas. A forma correta:
| |
Exemplo com Classe e Argumento Mutável
| |
A mesma lista é compartilhada por todas as instâncias quando passada como valor padrão mutável. Correção:
| |
Boas Práticas para Evitar Problemas com Argumentos Mutáveis
Nunca use tipos mutáveis como valores padrão de argumentos. Prefira usar
Nonee inicialize a variável dentro da função.Evite efeitos colaterais em funções. Funções devem ser previsíveis e sempre retornar resultados baseados em seus argumentos.
Prefira tipos imutáveis para valores padrão. Imutáveis como
int,stretuplenão causam esse tipo de problema.Ao lidar com objetos mutáveis, clone-os quando necessário. Use métodos como
copy()ou slicing para evitar alterações inesperadas.Teste cuidadosamente funções que recebem parâmetros opcionais. Garanta que o estado de chamadas anteriores não afete as subsequentes.
Documente o comportamento esperado de seus métodos, especialmente em bibliotecas e APIs. Indique claramente se objetos mutáveis são compartilhados ou não.
Dominar essas técnicas ajuda a produzir código Python mais resiliente e menos propenso a bugs difíceis de detectar, essencial para engenheiros de software que buscam qualidade profissional em seus projetos.
Contate-nos no Mastodon em @riverfount@bolha.us.