Solucionado (ver solução)
Solucionado
(ver solução)
1
resposta

Sobre Shallow Copy e Deep Copy Python 3.7

Dei uma lida no tópico da Alura, sugerido no curso, sobre copia profunda e copia rasa e executando os teste tanto a copia rasa quanto a profunda não tiveram uma reação diferente ambas trabalharam igual, gostaria de saber porque. Segue o Código com os resultados:

# Inicio
from copy import deepcopy
# Testando Copia Rasa

l1 = [1, 2, 3, 6, 9, 30]
l2 = l1

print(f'L1 = {l1} L2 = {l2}')
print(f'ID L1 = {id(l1)} ID L2 = {id(l2)}')
# Resultado
# L1 = [123456] L2 = [123456]
# ID L1 = 6054536 ID L2 = 6054536

l2 = l1[:]

print(f'L1 = {l1} L2 = {l2}')
print(f'ID L1 = {id(l1)} ID L2 = {id(l2)}')
# Resultado
# L1 = [123456] L2 = [123456]
# ID L1 = 33710728 ID L2 = 34201288

l1.remove(3)
print(f'L1 = {l1} L2 = {l2}')
print(f'ID L1 = {id(l1)} ID L2 = {id(l2)}')
# Resultado
# L1 = [1, 2, 6, 9, 30] L2 = [1, 2, 3, 6, 9, 30]
# ID L1 = 31927944 ID L2 = 32268936

# Testando Copia Profunda

l2 = deepcopy(l1)
l1.remove(6)
print(f'L1 = {l1} L2 = {l2}')
print(f'ID L1 = {id(l1)} ID L2 = {id(l2)}')
# Resultado
# L1 = [1, 2, 9, 30] L2 = [1, 2, 6, 9, 30]
# ID L1 = 34484040 ID L2 = 42165128
1 resposta
solução!

Opa Luan, tudo bem?

Para ajudar na resposta vou criar uma classe teste que tem um atributo número, tudo bem?

class Teste:
    def __init__(self, numero):
        self.numero = numero

    def __repr__(self):
        return str(self.numero)

A partir dela, criamos seis objetos testes:

teste1 = Teste(1)
teste2 = Teste(2)
teste3 = Teste(3)
teste6 = Teste(6)
teste9 = Teste(9)
teste30 = Teste(30)

Quando atribuirmos l1 em l2, o que ocorre é que as duas variáveis apontam para o mesmo endereço de memória, por isso, o id das duas é igual:

l1 = [teste1, teste2, teste3, teste6, teste9, teste30]
l2 = l1

print(f'L1 = {l1} L2 = {l2}')
print(id(l1) == id(l2)) # por compartilhar o mesmo endereço de memória, o id é o mesmo
# # Resultado
# L1 = [1, 2, 3, 6, 9, 30] L2 = [1, 2, 3, 6, 9, 30]
# True

Quando utilizamos a cópia rasa, criamos outra lista, ou seja, os ids das listas são diferentes, mas o objetos dentro dessa lista tem o mesmo id, isto é, apontam para o mesmo endereço de memória dos objetos de l1. Podemos ver isso quando trocamos o número de um objeto teste, as duas listas tem os valores alterados, mesmo sendo listas diferentes:

# Testando Copia Rasa

teste1 = Teste(1)
teste2 = Teste(2)
teste3 = Teste(3)
teste6 = Teste(6)
teste9 = Teste(9)
teste30 = Teste(30)

l1 = [teste1, teste2, teste3, teste6, teste9, teste30]
l2 = l1[:]

l1[2].numero = 7
print('teste3 é atribuído número 7')

print(f'Cópia rasa L1 = {l1} L2 = {l2}')
print(id(l1) == id(l2))
# # Resultado
# teste3 é atribuído número 7
# Cópia rasa L1 = [1, 2, 7, 6, 9, 30] L2 = [1, 2, 7, 6, 9, 30]
# False

Já na cópia profunda, além de uma lista nova, os objetos nas duas listas são diferentes. Ou seja, quando alteramos o número de um objeto teste, ele não é alterado em l2:

# Testando Copia Profunda

teste1 = Teste(1)
teste2 = Teste(2)
teste3 = Teste(3)
teste6 = Teste(6)
teste9 = Teste(9)
teste30 = Teste(30)

l1 = [teste1, teste2, teste3, teste6, teste9, teste30]

l2 = deepcopy(l1)

print('teste3 é atribuído número 7')
l1[2].numero = 7

print(f'Cópia produnfa L1 = {l1} L2 = {l2}')
print(id(l1) == id(l2))
# # Resultado
# teste3 é atribuído número 7
# Cópia produnfa L1 = [1, 2, 7, 6, 9, 30] L2 = [1, 2, 3, 6, 9, 30]
# False

No caso, tanto na cópia rasa quanto na cópia profunda, por serem listas diferentes, podemos remover um objeto de uma lista sem afetar a outra. Isso porque é uma lista está deixando de apontar para o objeto, mas a outra lista ainda mantém a referência.