Python - A diferença entre “Deep Copy e Shallow Copy”

Quando estamos trabalhando com containers (objetos como listas, sets e dicionários) em Python, temos que tomar bastante cuidado ao criar cópias desses objetos.
Isso porque um programador distraído pode cometer um erro sutil, mas grave: efetuar um shallow copy quando na verdade precisava de um deep copy.
- Um shallow copy, ou “cópia superficial” (convenhamos que é preferível adotar o termo em inglês) cria um novo objeto e preenche esse objeto com referências para os itens contidos no objeto original. Dessa forma qualquer mudança em um dos objetos será também refletida no outro.

- Um deep copy, ou “cópia profunda” cria um novo objeto, e o popula com cópias dos itens do container original. Ou seja, qualquer modificação em um objeto, não será refletida no outro.

Como visto nesses exemplos, ao efetuar um deep copy geramos um objeto completamente independente, e, no shallow copy, criamos um novo objeto mas inserimos nele referências para os itens do objeto original.
A explicação para esses diferentes tipos de cópia talvez possa ser entendida mais facilmente por aqueles que já tiveram contato com o conceito de ponteiros, comum em linguagens de mais baixo nível, como C.
O que acontece é que cada um dos elementos do nosso array original está alocado em uma determinada posição da memória RAM de seu computador. Ao efetuarmos um shallow copy, nosso novo array vai “apontar” para essa seção de memória do array original, compartilhando-a. Enquanto que, com o deep copy, os itens do array original serão clonados em outra seção de memória.
Entendeu bem? É bom ficar ligado(a), porque usar o método incorreto de cópia é o tipico erro que passa despercebido no código, e pode gerar uma certa dor de cabeça para debugar.
Espero que tenha gostado. Qualquer dúvida deixa aí nos comentários ;)