Atribuição e Referência em Python

PythonBeginner
Pratique Agora

Introdução

Neste laboratório, abordaremos os fundamentos da atribuição e referência em Python. Exploraremos como o Python lida com atribuições, como criar referências e como trabalhar com objetos mutáveis e imutáveis.

Introdução às Atribuições em Python

Em Python, a atribuição é o processo de vincular um nome a um objeto. As instruções de atribuição têm a seguinte forma geral:

variable = expression

A expressão no lado direito é avaliada, e seu valor é atribuído à variável no lado esquerdo.

Vamos analisar um exemplo simples:

Teste Simples

Abra o Terminal e digite o seguinte comando no terminal.

python3

Em seguida, insira o seguinte código.

## Assign the value 42 to the variable 'x' and print it.
x = 42
print(x)

Output:

42

Aqui, atribuímos o valor 42 à variável x usando o operador =. Em seguida, imprimimos o valor de x.

Compreendendo as Referências

Em Python, as variáveis são referências a objetos. Quando você atribui um valor a uma variável, você está, na verdade, criando uma referência ao objeto que representa o valor.

Aqui está um exemplo para ilustrar este conceito:

## Illustrate Python references.
x = [1, 2, 3]
y = x
y.append(4)

print("x:", x)
print("y:", y)

Output:

x: [1, 2, 3, 4]
y: [1, 2, 3, 4]

Neste exemplo, tanto x quanto y se referem ao mesmo objeto lista. Quando modificamos a lista através da referência y adicionando 4, a mudança é refletida em x e y.

Objetos Mutáveis e Imutáveis

Python possui dois tipos de objetos: mutáveis e imutáveis.

Objetos mutáveis podem ser modificados após sua criação. Listas, dicionários e conjuntos são exemplos de objetos mutáveis.

Objetos imutáveis não podem ser modificados após sua criação. Inteiros, floats, strings e tuplas são exemplos de objetos imutáveis.

Vamos analisar um exemplo que demonstra a diferença entre objetos mutáveis e imutáveis:

## Mutable object example
mutable_list = [1, 2, 3]
another_mutable_list = mutable_list
another_mutable_list.append(4)
print("mutable_list:", mutable_list)

Output:

mutable_list: [1, 2, 3, 4]

mutable_list adiciona um 4 ao final da lista porque são objetos mutáveis, mas objetos imutáveis não podem ser modificados após sua criação.

## Immutable object example
immutable_string = "hello"
another_immutable_string = immutable_string
another_immutable_string = another_immutable_string.upper()
print("immutable_string:", immutable_string)

Output:

immutable_string: hello

Não houve nenhuma alteração, e se quisermos alterar a immutable_string da seguinte forma, o shell do Python lançará um TypeError:

immutable_string[0] = '1'

Output:

TypeError: 'str' object does not support item assignment

Exemplos

Vamos ver mais alguns exemplos para reforçar os conceitos que aprendemos:

Exemplo 1: Função com argumento padrão mutável

Evite usar objetos mutáveis como argumentos padrão em funções:

def bad_append(new_item, a_list=[]):
    a_list.append(new_item)
    return a_list

print(bad_append('one'))

Output:

['one']

Parece bom, mas se chamarmos esta função novamente:

print(bad_append('two'))

Output:

['one', 'two']

O problema aqui é que o valor padrão de a_list é avaliado no momento da definição da função. Portanto, toda vez que você chama a função, você obtém o mesmo valor padrão. A maneira correta é criá-lo em tempo de execução, dentro da função.

def append_to_list(item: int, a_list: list = None) -> list:
    """Append an item to a list and return the updated list."""
    if a_list is None:
        a_list = []
    a_list.append(item)
    return a_list

list_a = append_to_list(1, [1, 2, 3])
print(list_a)

Output:

[1, 2, 3, 1]

Exemplo 2: Copiando objetos mutáveis

Use o módulo copy para criar um novo objeto quando você quiser trabalhar com uma cópia de um objeto mutável:

import copy

## Demonstrate the use of the copy module.
original_list = [1, 2, 3]
copied_list = copy.copy(original_list)
copied_list.append(4)

print("original_list:", original_list)
print("copied_list:", copied_list)

Output:

original_list: [1, 2, 3]
copied_list: [1, 2, 3, 4]

Neste exemplo, copied_list é um novo objeto que é uma cópia de original_list. Quando adicionamos 4 a copied_list, original_list permanece inalterada.

Exemplo 3: Cópia profunda de objetos mutáveis

Para objetos mutáveis aninhados, usar a função copy não funciona:

## your copy example here
original_nested_list = [[1, 2], [3, 4]]
copied_nested_list = copy.copy(original_nested_list)
copied_nested_list[0].append(5)

print("original_nested_list:", original_nested_list)
print("copied_nested_list:", copied_nested_list)

Output:

original_nested_list: [[1, 2, 5], [3, 4]]
copied_nested_list: [[1, 2, 5], [3, 4]]

Podemos ver que quando adicionamos 5 a copied_nested_list, a original_nested_list também adiciona 5. Portanto, você deve usar a função deepcopy em vez disso:

## your deepcopy example here
original_nested_list = [[1, 2], [3, 4]]
deep_copied_list = copy.deepcopy(original_nested_list)
deep_copied_list[0].append(5)

print("original_nested_list:", original_nested_list)
print("deep_copied_list:", deep_copied_list)

Output:

original_nested_list: [[1, 2], [3, 4]]
deep_copied_list: [[1, 2, 5], [3, 4]]

Neste exemplo, a função deepcopy copia a original_nested_list recursivamente, enquanto a função copy cria um objeto de referência para os dados de primeiro nível da original_nested_list.

Resumo

Neste tutorial de programação Python, cobrimos os fundamentos da atribuição e referência em Python. Exploramos como o Python lida com atribuições, como criar referências e como trabalhar com objetos mutáveis e imutáveis. Ao entender esses conceitos, você estará mais bem equipado para escrever código Python eficiente e correto.