DoesItHold

Por que um argumento padrão mutável vaza estado em Python

Um argumento padrão em Python é avaliado uma vez, quando a função é definida, e não a cada chamada. Se esse padrão for uma lista mutável, toda chamada que omite o argumento compartilha a mesma lista.

A resposta rápida

Não use um valor mutável, como uma lista, como argumento padrão. Use None e crie uma lista nova dentro da função quando nenhum argumento for fornecido.

Um exemplo mínimo

Com bug: a lista padrão é criada uma vez e reusada
def record(label, history=[]):
    history.append(label)
    return history
Corrigido: uma lista nova é criada por chamada
def record(label, history=None):
    if history is None:
        history = []
    history.append(label)
    return history

Na versão com bug, duas chamadas sem o argumento opcional adicionam itens à mesma lista, então os resultados se acumulam. A verificação de None cria uma lista própria para cada chamada.

Como depurar

  1. Chame a função duas vezes seguidas sem passar o argumento opcional.
  2. Se o segundo resultado contém dados da primeira chamada, o valor padrão está sendo compartilhado.
  3. Procure um padrão mutável: uma lista, dict ou set na assinatura.
  4. Substitua por None e construa o contêiner dentro da função.

Correções erradas comuns

  • Limpar a lista no início da função, o que muta um objeto compartilhado que outros podem estar segurando.
  • Copiar o padrão dentro da função mas manter o padrão mutável na assinatura.
  • Usar uma tupla como padrão e depois tentar dar append nela.

Limites deste guia

Este é o caso clássico de padrão mutável. Armadilhas relacionadas incluem atributos de classe mutáveis e caches compartilhados. O desafio foca na versão de argumento padrão para que a causa seja inequívoca.

Referências oficiais

  1. FAQ de programação do Python — valores padrão compartilhados
  2. Tutorial do Python — valores padrão de argumentos
  3. Referência da linguagem Python — definições de função

Pronto para experimentar?

Corrigir este bug em um desafio grátis

Páginas relacionadas