Argumentos Mutáveis de Função

O Python possui uma variedade de tipos de dados, alguns dos quais podem ser modificados após a sua criação e outros não. Quando falamos de tipos que podem ser alterados, referimo-nos a eles como tipos "mutáveis". Em contraste, aqueles que não podem ser alterados são chamados de tipos "imutáveis".

Tipos Mutáveis

Os tipos mutáveis mais comuns são lists, dicts e sets. Aqui está um exemplo de uma lista:
fruits = ['apple', 'banana', 'cherry']
print(fruits, type(fruits))  # ['apple', 'banana', 'cherry'] <class 'list'>
Com uma list, pode alterar os seus elementos, adicionar novos ou remover existentes:
fruits[1] = 'blueberry'       # Muda 'banana' para 'blueberry'
fruits.append('dragonfruit')  # Adiciona 'dragonfruit' ao fim da lista
print(fruits)                 # ['apple', 'blueberry', 'cherry', 'dragonfruit']

Tipos Imutáveis

Por outro lado, exemplos de tipos imutáveis são ints, floats, strings e tuples. Uma vez criados, não pode alterar o seu conteúdo. Aqui está um exemplo de uma string:
message = 'hello'
print(message, type(message))  # hello <class 'str'>
Se tentar alterar parte da string, o Python não o permitirá:
message[0] = 'H'  # Tentar mudar 'h' para 'H' dará um TypeError
Como é que int é imutável? Não podemos mudar o valor com += ou -=?
Quando falamos sobre mutabilidade no Python, referimo-nos à capacidade de o valor real armazenado na memória poder ser alterado. Por exemplo, quando temos uma lista, podemos alterar um item nessa lista, e continua a ser a mesma lista na memória.
Inteiros no Python são imutáveis. Isto significa que o valor na memória não pode ser alterado. Se tivermos um inteiro, a = 5, e realizarmos uma operação como a += 2, pode parecer que alterámos a. No entanto, o que o Python realmente fez foi criar um novo objeto na memória com o valor de 7 e atualizar a para apontar para esse novo objeto. O 5 original não foi alterado na memória — é por isso que ints são considerados imutáveis.
a = 5
print(id(a))  # Isto imprime a localização na memória de a. Vamos supor que é 1001

a += 2
print(a)      # Isto imprime 7
print(id(a))  # Isto imprimirá uma localização de memória diferente, digamos 1002
A função id em Python retorna a identidade de um objeto, que é única e constante durante a vida útil do objeto. Portanto, quando vemos que a identidade de a mudou após a operação a += 2, é um sinal claro de que a agora aponta para um novo objeto na memória. O inteiro original 5 não foi alterado, confirmando que os inteiros são realmente imutáveis em Python.

Argumentos Mutáveis em Funções

Quando passamos um objeto mutável (como uma lista) para uma função, o Python fornece à função uma referência a esse objeto. Isto significa que, se a função modificar o objeto mutável, essa modificação também será visível fora da função.
Vamos utilizar uma função que recebe uma lista e adiciona um elemento a ela:
def add_item(my_list):
    my_list.append('added item')  # Adiciona um novo item à lista

shopping_list = ['apples', 'bananas', 'cherries']
print(shopping_list)  # Imprime: ['apples', 'bananas', 'cherries']

# Agora usamos a função para adicionar um item à nossa lista de compras
add_item(shopping_list)
print(shopping_list)  # Imprime: ['apples', 'bananas', 'cherries', 'added item']
Como pode ver, quando imprimimos shopping_list após chamar a função add_item, a lista tinha um novo item. Isto aconteceu mesmo sem modificarmos diretamente shopping_list fora da função.
No entanto, é essencial compreender que, se atribuir um novo valor ao objeto mutável inteiro dentro da função, isso não afetará o objeto original. Isto porque está a atribuir uma nova referência à variável local da função, não modificando o objeto original. Vamos ver um exemplo disto:
def change_list(my_list):
    my_list = ['entirely', 'new', 'list']  # Isto não afetará a lista original

shopping_list = ['apples', 'bananas', 'cherries']
change_list(shopping_list)
print(shopping_list)  # Ainda imprime: ['apples', 'bananas', 'cherries']
Embora tenhamos chamado a função change_list com shopping_list como argumento, o conteúdo de shopping_list não mudou. Isto porque, dentro da função, my_list recebeu uma nova referência (para uma lista completamente nova), enquanto a referência de shopping_list permaneceu intocada.
A principal conclusão aqui é: quando passa um objeto mutável para uma função em Python, lembre-se de que, se a função alterar o objeto (como adicionar um item a uma lista), a alteração é permanente e visível fora da função. Porém, se atribuir um novo valor ao objeto inteiro dentro da função, isso não afetará o objeto original.
 
To check your solution you need to sign in
Sign in to continue