Como usar o deep copy e shallow copy no Python?
Cópia Profunda vs Cópia Rasa de Objetos em Python
Por Dan Bader
Em Python, fazer uma atribuição de variáveis não cria cópias de objetos, apenas faz com que os nomes se refiram a um objeto. Isso geralmente não faz diferença para objetos imutáveis.
No entanto, para trabalhar com objetos mutáveis ou coleções de objetos mutáveis, pode ser útil criar cópias reais ou clones desses objetos.
Às vezes, você pode precisar de cópias em que possa fazer modificações sem modificar automaticamente o objeto original ao mesmo tempo. Neste artigo, vou explicar como copiar ou “clonar” objetos em Python 3 e algumas ressalvas envolvidas.
Fazendo Cópias Rasas
As coleções mutáveis embutidas em Python, como listas, dicionários e conjuntos, podem ser copiadas chamando suas funções de fábrica em uma coleção existente:
No entanto, esse método não funciona para objetos personalizados e, além disso, ele cria apenas cópias rasas. Para objetos compostos como listas, dicionários e conjuntos, há uma diferença importante entre cópias rasas e profundas:
-
Uma cópia rasa cria um novo objeto de coleção e então popula-o com referências aos objetos filhos encontrados no objeto original. Em essência, uma cópia rasa é apenas um nível de profundidade. O processo de cópia não se repete e, portanto, não cria cópias dos objetos filhos em si.
-
Uma cópia profunda faz o processo recursivamente. Significa que primeiro se constrói um novo objeto de coleção e, em seguida, o preenche recursivamente com cópias dos objetos filhos encontrados no objeto original. Copiar um objeto dessa maneira percorre toda a árvore de objetos para criar um clone totalmente independente do objeto original e de todos os seus filhos.
Agora vamos olhar alguns exemplos para deixar clara essa diferença entre cópias profundas e rasas.
Exemplo de Cópia Rasa
No exemplo a seguir, vamos criar uma nova lista aninhada e fazer uma cópia rasa dela usando a função list()
:
Isso significa que ys
agora será um objeto novo e independente com o mesmo conteúdo que xs
. Podemos verificar isso inspecionando ambos os objetos:
Para confirmar que ys
é realmente independente do original, vamos fazer um pequeno experimento. Podemos adicionar uma nova sublista ao original (xs
) e em seguida verificar se essa modificação não afetou a cópia (ys
):
Como podemos ver, isso teve o efeito esperado. Modificar a lista copiada em um nível superficial não foi um problema.
No entanto, como fizemos apenas uma cópia rasa da lista original, ys
ainda contém referências aos objetos filhos originais.
Fazendo Cópias Profundas
Para fazer uma cópia profunda, podemos usar a biblioteca copy
do Python:
Agora, ys
é um clone completo de xs
. Vamos verificar novamente:
A diferença é que, com a cópia profunda, os objetos filhos também são clonados. Isso é confirmado quando fazemos uma modificação superficial em xs
e verificamos que ys
permanece inalterada:
Copiando Objetos Arbitrários em Python
Para copiar objetos personalizados, a classe do objeto pode implementar o método mágico __copy__()
e/ou __deepcopy__()
para controlar o processo de cópia.
Tomemos como exemplo uma classe Person
:
Podemos fazer uma cópia rasa dessa classe usando a função copy.copy()
da biblioteca copy
:
No entanto, se quisermos fazer uma cópia profunda, precisamos implementar o método __copy__()
na classe Person
:
Agora podemos fazer uma cópia profunda usando a função copy.deepcopy()
:
Isso nos dará um clone completo do objeto p1
com todos os seus atributos e métodos.
3 Coisas para Lembrar
-
Atribuição de variáveis em Python não cria cópias de objetos, apenas faz com que os nomes se refiram a um objeto.
-
Cópias rasas criam um novo objeto e popula-o com referências aos objetos filhos encontrados no objeto original. As modificações superficiais em cópias rasas não afetam o objeto original, mas as modificações nos objetos filhos sim.
-
Cópias profundas, por outro lado, criam um clone totalmente independente do objeto original e de todos os seus filhos. As modificações em cópias profundas não afetam nem o objeto original nem seus filhos.
Em resumo, ao trabalhar com objetos mutáveis em Python, é importante entender a diferença entre cópias rasas e profundas. Dependendo do caso de uso, você pode escolher o método de cópia mais adequado para evitar efeitos colaterais indesejados.
Gostou deste artigo? Compartilhe com seus amigos desenvolvedores e continue aprendendo mais sobre Python!