import copy
a = "deepak"
b = 1, 2, 3, 4
c = [1, 2, 3, 4]
d = {1: 10, 2: 20, 3: 30}
a1 = copy.copy(a)
b1 = copy.copy(b)
c1 = copy.copy(c)
d1 = copy.copy(d)
print("immutable - id(a)==id(a1)", id(a) == id(a1))
print("immutable - id(b)==id(b1)", id(b) == id(b1))
print("mutable - id(c)==id(c1)", id(c) == id(c1))
print("mutable - id(d)==id(d1)", id(d) == id(d1))
Eu recebo os seguintes resultados:
immutable - id(a)==id(a1) True
immutable - id(b)==id(b1) True
mutable - id(c)==id(c1) False
mutable - id(d)==id(d1) False
Se eu fizer uma cópia em profundidade:
a1 = copy.deepcopy(a)
b1 = copy.deepcopy(b)
c1 = copy.deepcopy(c)
d1 = copy.deepcopy(d)
os resultados são os mesmos:
immutable - id(a)==id(a1) True
immutable - id(b)==id(b1) True
mutable - id(c)==id(c1) False
mutable - id(d)==id(d1) False
Se eu trabalhar em operações de atribuição:
a1 = a
b1 = b
c1 = c
d1 = d
então os resultados são:
immutable - id(a)==id(a1) True
immutable - id(b)==id(b1) True
mutable - id(c)==id(c1) True
mutable - id(d)==id(d1) True
Alguém pode explicar o que exatamente faz a diferença entre as cópias? É algo relacionado a objetos mutáveis e imutáveis? Se sim, você pode me explicar?
fonte
list_=[[1,2],[3,4]] newlist = list_.copy() list_[0]=[7,8] print(list_) print(newlist)
Anewlist
exibição continua[[1, 2], [3, 4]]
. Maslist_[0]
é uma lista que é mutável.list_[0]
é mutável, mas você não o está modificando / modificando. Tentelist_[0].append(9)
ou emlist_[0][0] = 7
vez disso.Para objetos imutáveis, não há necessidade de copiar porque os dados nunca mudam; portanto, o Python usa os mesmos dados; ids são sempre os mesmos. Para objetos mutáveis, como eles podem mudar potencialmente, a cópia [superficial] cria um novo objeto.
A cópia profunda está relacionada a estruturas aninhadas. Se você tiver uma lista de listas, copie
copies
também as listas aninhadas, para que seja uma cópia recursiva. Com apenas copiar, você tem uma nova lista externa, mas listas internas são referências.A atribuição não copia. Simplesmente define a referência para os dados antigos. Então você precisa copiar para criar uma nova lista com o mesmo conteúdo.
fonte
With just copy, you have a new outer list but inner lists are references.
Para as listas internas, a copiada seria influenciada pela original? Eu crio uma lista de listas comolist_=[[1,2],[3,4]] newlist = list_.copy() list_[0]=[7,8]
enewlist
as mesmas permanecem, a lista interna é referência?list_[0][0] = 7
Para objetos imutáveis, criar uma cópia não faz muito sentido, pois eles não vão mudar. Para objetos mutáveis
assignment
,copy
edeepcopy
comporta-se diferentemente. Vamos falar sobre cada um deles com exemplos.Uma operação de atribuição simplesmente atribui a referência da fonte ao destino, por exemplo:
Agora
i
ej
tecnicamente se refere à mesma lista. Ambosi
ej
têm o mesmo endereço de memória. Qualquer atualização para um deles será refletida no outro. por exemplo:Por outro lado
copy
edeepcopy
cria uma nova cópia da variável. Portanto, agora as alterações na variável original não serão refletidas na variável de cópia e vice-versa. Contudocopy(shallow copy)
, não cria uma cópia de objetos aninhados, apenas copia a referência de objetos aninhados. A cópia em profundidade copia todos os objetos aninhados recursivamente.Alguns exemplos para demonstrar o comportamento
copy
edeepcopy
:Exemplo de lista simples usando
copy
:Exemplo de lista aninhada usando
copy
:Exemplo de lista simples usando
deepcopy
:Exemplo de lista aninhada usando
deepcopy
:fonte
Vamos ver em um exemplo gráfico como o seguinte código é executado:
fonte
a, b, c, d, a1, b1, c1 e d1 são referências a objetos na memória, identificados exclusivamente por seus IDs.
Uma operação de atribuição faz uma referência ao objeto na memória e atribui essa referência a um novo nome.
c=[1,2,3,4]
é uma atribuição que cria um novo objeto de lista que contém esses quatro números inteiros e atribui a referência a esse objetoc
.c1=c
é uma atribuição que leva a mesma referência ao mesmo objeto e a atribui a issoc1
. Como a lista é mutável, tudo o que acontecer com essa lista ficará visível, independentemente de você ser acessado atravésc
ouc1
, porque ambos fazem referência ao mesmo objeto.c1=copy.copy(c)
é uma "cópia superficial" que cria uma nova lista e atribui a referência à nova listac1
.c
ainda aponta para a lista original. Portanto, se você modificar a lista emc1
, a lista quec
se refere não será alterada.O conceito de cópia é irrelevante para objetos imutáveis, como números inteiros e seqüências de caracteres. Como você não pode modificar esses objetos, nunca é necessário ter duas cópias do mesmo valor na memória em locais diferentes. Portanto, números inteiros e seqüências de caracteres, e alguns outros objetos aos quais o conceito de cópia não se aplica, são simplesmente reatribuídos. É por isso que seus exemplos
a
eb
resultam em IDs idênticos.c1=copy.deepcopy(c)
é uma "cópia profunda", mas funciona da mesma forma que uma cópia superficial neste exemplo. As cópias profundas diferem das cópias rasas, pois as cópias rasas criarão uma nova cópia do objeto em si, mas as referências dentro desse objeto não serão copiadas. No seu exemplo, sua lista possui apenas números inteiros (imutáveis) e, como discutido anteriormente, não há necessidade de copiá-los. Portanto, a parte "profunda" da cópia profunda não se aplica. No entanto, considere esta lista mais complexa:e = [[1, 2],[4, 5, 6],[7, 8, 9]]
Esta é uma lista que contém outras listas (você também pode descrevê-la como uma matriz bidimensional).
Se você executar uma "cópia superficial"
e
, copiando-a parae1
, descobrirá que o ID da lista é alterado, mas cada cópia da lista contém referências às mesmas três listas - as listas com números inteiros. Isso significa que, se você fosse fazere[0].append(3)
,e
seria[[1, 2, 3],[4, 5, 6],[7, 8, 9]]
. Mase1
também seria[[1, 2, 3],[4, 5, 6],[7, 8, 9]]
. Por outro lado, se você fez posteriormentee.append([10, 11, 12])
,e
seria[[1, 2, 3],[4, 5, 6],[7, 8, 9],[10, 11, 12]]
. Mase1
ainda seria[[1, 2, 3],[4, 5, 6],[7, 8, 9]]
. Isso ocorre porque as listas externas são objetos separados, que inicialmente contêm três referências a três listas internas. Se você modificar as listas internas, poderá ver essas alterações, independentemente de visualizá-las através de uma cópia ou de outra. Mas se você modificar uma das listas externas como acima,e
contém três referências às três listas originais e mais uma referência a uma nova lista. Ee1
ainda contém apenas as três referências originais.Uma 'cópia profunda' não apenas duplicaria a lista externa, mas também entraria nas listas e duplicaria as listas internas, para que os dois objetos resultantes não contenham nenhuma das mesmas referências (no que diz respeito a objetos mutáveis) . Se as listas internas tivessem listas adicionais (ou outros objetos, como dicionários), elas também seriam duplicadas. Essa é a parte 'profunda' da 'cópia profunda'.
fonte
No python, quando atribuímos objetos como list, tuples, dict, etc a outro objeto geralmente com um sinal '=', o python cria cópias por referência . Ou seja, digamos que temos uma lista de lista como esta:
e atribuímos outra lista a essa lista, como:
então, se imprimirmos a lista2 no terminal python, obteremos o seguinte:
Tanto list1 como list2 estão apontando para o mesmo local de memória, qualquer alteração em qualquer um deles resultará em alterações visíveis nos dois objetos, ou seja, os dois objetos estão apontando para o mesmo local de memória. Se mudarmos a lista1 assim:
então list1 e list2 serão:
Agora, na cópia Raso , quando dois objetos são copiados via cópia rasa, o objeto filho de ambos os objetos pai se refere ao mesmo local da memória, mas quaisquer novas alterações adicionais em qualquer objeto copiado serão independentes entre si. Vamos entender isso com um pequeno exemplo. Suponha que tenhamos esse pequeno trecho de código:
Observe que a lista2 permanece inalterada, mas se fizermos alterações nos objetos filho, como:
então list1 e list2 serão alteradas:
Agora, a cópia profunda ajuda a criar objetos completamente isolados um do outro. Se dois objetos forem copiados via Deep Copy, o pai e o filho apontarão para um local de memória diferente. Exemplo:
Observe que a lista2 permanece inalterada, mas se fizermos alterações nos objetos filho, como:
a lista2 também não será afetada, pois todos os objetos filho e objeto pai apontam para um local de memória diferente:
Espero que ajude.
fonte
O código abaixo demonstra a diferença entre atribuição, cópia rasa usando o método de cópia, cópia rasa usando a (fatia) [:] e a cópia em profundidade. O exemplo abaixo usa listas aninhadas, tornando as diferenças mais evidentes.
fonte
O GIST a ser adotado é o seguinte: Lidar com listas rasas (sem sub-listas, apenas elementos únicos) usando "atribuição normal" aumenta um "efeito colateral" quando você cria uma lista superficial e depois cria uma cópia dessa lista usando "atribuição normal" . Esse "efeito colateral" ocorre quando você altera qualquer elemento da lista de cópias criada, porque altera automaticamente os mesmos elementos da lista original. É quando isso é
copy
útil, pois não altera os elementos da lista original ao alterar os elementos de cópia.Por outro lado,
copy
também tem um "efeito colateral", quando você tem uma lista que contém listas (sub_lists) e adeepcopy
resolve. Por exemplo, se você criar uma grande lista que contém listas aninhadas (sub_lists) e criar uma cópia dessa grande lista (a lista original). O "efeito colateral" surgiria quando você modificar as sub-listas da lista de cópias, que modificariam automaticamente as sub-listas da grande lista. Às vezes (em alguns projetos) você deseja manter a grande lista (sua lista original) sem modificações, e tudo o que você deseja é fazer uma cópia de seus elementos (sub_lists). Para isso, sua solução é usar odeepcopy
que cuidará desse "efeito colateral" e fará uma cópia sem modificar o conteúdo original.Os diferentes comportamentos
copy
edeep copy
operações dizem respeito apenas a objetos compostos (ou seja: objetos que contêm outros objetos, como listas).Aqui estão as diferenças ilustradas neste exemplo de código simples:
Primeiro
vamos verificar como
copy
(raso) se comporta, criando uma lista original e uma cópia desta lista:Agora, vamos executar alguns
print
testes e ver como a lista original se compara à sua lista de cópias:original_list e copy_list têm endereços diferentes
elementos da lista original e lista de cópias têm os mesmos endereços
sub_elements de original_list e copy_list têm os mesmos endereços
modificar elementos da lista original NÃO modifica os elementos da lista cópia
modificar elementos copy_list NÃO modifica elementos original_list
modificar sub_elements da lista original modificar automaticamente sub_elementos da cópia
modificar sub_elementos copy_list modificar automaticamente sub_elements original_list
Segundo
vamos verificar como
deepcopy
se comporta, fazendo o mesmo que fizemos comcopy
(criando uma lista original e uma cópia desta lista):Agora, vamos executar alguns
print
testes e ver como a lista original se compara à sua lista de cópias:original_list e copy_list têm endereços diferentes
elementos da lista original e lista de cópias têm os mesmos endereços
sub_elements de original_list e copy_list têm endereços diferentes
modificar elementos da lista original NÃO modifica os elementos da lista cópia
modificar elementos copy_list NÃO modifica elementos original_list
modificar sub_elements da lista original NÃO modifica os sub_elementos da cópia
modificar sub_elementos copy_list NÃO modifica sub_elements original_list
fonte
Não tenho certeza se isso foi mencionado acima ou não, mas é muito importante entender que .copy () cria referência ao objeto original. Se você alterar o objeto copiado - você altera o objeto original. .deepcopy () cria um novo objeto e faz uma cópia real do objeto original para um novo. Alterar um novo objeto copiado em profundidade não afeta o objeto original.
E sim, .deepcopy () copia o objeto original recursivamente, enquanto .copy () cria um objeto de referência para dados de primeiro nível do objeto original.
Portanto, a diferença de cópia / referência entre .copy () e .deepcopy () é significativa.
fonte
A cópia profunda está relacionada a estruturas aninhadas. Se você tiver uma lista de listas, copie em profundidade as listas aninhadas também, portanto, é uma cópia recursiva. Com apenas copiar, você tem uma nova lista externa, mas listas internas são referências. A atribuição não copia. Para Ex
Resultado
[[0, 1, 2, 3, 3], 4, 5] [[0, 1, 2, 3, 3], 4, 5, 3] Copie o método copiar o conteúdo da lista externa para uma nova lista, mas a lista interna é ainda é o mesmo para as duas listas. Se você fizer alterações na lista interna de qualquer lista, isso afetará as duas.
Mas se você usar a cópia Profunda, ela também criará uma nova instância para a lista interna.
Resultado
[0, 1, 2, 3] [[0, 1, 2, 3, 3], 4, 5, 3]
fonte
fonte
a
não é uma cópia em profundidade delst
!