Argumentos Opcionais Mutáveis em Python

mdslino

Marcelo Lino

Posted on February 27, 2023

Argumentos Opcionais Mutáveis em Python

Argumentos deveriam ser coisas simples, não é mesmo? Você passa um valor para a função e ela faz o que você espera. Mas o que acontece quando a sua função não te obriga a passar um valor e trabalha com um valor padrão?

Uma função de soma que recebe dois valores e retorna a soma deles, porém caso nenhum valor seja inserido os argumentos assumem o valor 10 para cada um, retornando assim 20.

def soma(a=10, b=10):
    return a + b
Enter fullscreen mode Exit fullscreen mode

Nesse exemplo os valores padrões são imutáveis, então a cada operação não há modificação no seu conteúdo.

Agora o que acontece se modificamos o valor padrão para uma lista ou um dicionário?

Problema

from random import randint

def mutable_arguments(a_list=[], a_dict={}):
    a_list.append(randint(0, 100))
    a_dict[randint(0, 100)] = randint(0, 100)

    print(f"A lista agora contém os seguintes items: {a_list}")
    print(f"O dicionário agora contém os seguintes items: {a_dict}", end="\n\n")

mutable_arguments()
mutable_arguments()
mutable_arguments()
Enter fullscreen mode Exit fullscreen mode

Essa execução gera a seguinte saída:

The local list a_list now contains: [43]
The local dict a_dict now contains: {50: 61}

The local list a_list now contains: [43, 74]
The local dict a_dict now contains: {50: 61, 128: 69}

The local list a_list now contains: [43, 74, 42]
The local dict a_dict now contains: {50: 61, 128: 69, 86: 79}
Enter fullscreen mode Exit fullscreen mode

Note que a cada execução a lista e o dicionário são modificados, isso acontece porque o interpretador do Python aloca cada função ou método na inicialização do programa, caso essa assinatura contenha inicializadores de objetos eles então serão instanciados e alocados em memória durante a inicialização.

Sendo assim, quando você executa seu código e altera esses mesmos valores, está alterando objetos já alocados e não criando novos a cada execução. O que pode ao final do programa gerar resultados inesperados.

Solução

Existem duas formas de resolver esse problema, a primeira é passar None como valor padrão e então verificar se o valor é None e então atribuir o valor padrão.

from random import randint

def immutable_arguments(a_list=None, a_dict=None):
    if a_list is None:
        a_list = []
    if a_dict is None:
        a_dict = {}

    a_list.append(randint(0, 100))
    a_dict[randint(0, 100)] = randint(0, 100)

    print(f"A lista agora contém os seguintes items: {a_list}")
    print(f"O dicionário agora contém os seguintes items: {a_dict}", end="\n\n")

immutable_arguments()
immutable_arguments()
immutable_arguments()
Enter fullscreen mode Exit fullscreen mode

Outra abordagem é reatribuir o valor padrão ou então um objeto mutável vazio.

from random import randint

def immutable_arguments(a_list=None, a_dict=None):
    a_list = a_list or []
    a_dict = a_dict or {}

    a_list.append(randint(0, 100))
    a_dict[randint(0, 100)] = randint(0, 100)

    print(f"A lista agora contém os seguintes items: {a_list}")
    print(f"O dicionário agora contém os seguintes items: {a_dict}", end="\n\n")

immutable_arguments()
immutable_arguments()
immutable_arguments()
Enter fullscreen mode Exit fullscreen mode

Em ambos os casos a saída será a seguinte:

A lista agora contém os seguintes items: [44]
O dicionário agora contém os seguintes items: {7: 37}

A lista agora contém os seguintes items: [39]
O dicionário agora contém os seguintes items: {28: 50}

A lista agora contém os seguintes items: [40]
O dicionário agora contém os seguintes items: {40: 99}
Enter fullscreen mode Exit fullscreen mode

Perceba que agora a cada execução os valores são reatribuídos e não mais modificados.

💖 💪 🙅 🚩
mdslino
Marcelo Lino

Posted on February 27, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Python For Beginners
python Python For Beginners

October 12, 2024

Data Types Part-05
python Data Types Part-05

August 29, 2024

The Tale of the Four Primal Forms
python The Tale of the Four Primal Forms

September 11, 2024

A Poetic Challenge !?
python A Poetic Challenge !?

September 17, 2024