Declaração de direitos autorais: este artigo é o artigo original do blogger e segue o contrato de direitos autorais CC 4.0 BY-SA . Anexe o link da fonte original e esta declaração para reimpressão.
Link para este artigo: https://blog.csdn.net/zsq8187/article/details/109907066
Estou aprendendo Python. Passei um dia escrevendo uma cópia das notas com base em minha própria revisão e teste de compreensão. Depois de pensar sobre isso, vamos publicar esta nota separadamente)
Artigo Diretório
Cópia superficial e cópia profunda
A atribuição de objetos em Python é feita diretamente por referência. Para copiar, você precisa usar o módulo de cópia na biblioteca padrão.
- Atribuição direta: passe o endereço de memória diretamente
- Cópia superficial
copy.copy()
: crie um novo objeto , copie os endereços de memória de todos os elementos dentro - Cópia profunda
copy.deepcopy()
: crie um novo objeto , copie o endereço de memória de forma imutável e crie recursivamente um novo objeto e copie o conteúdo se ele contiver uma variável (veja o tipo de tupla abaixo)- Na cópia aqui, você pode considerar temporariamente as tuplas com elementos variáveis como mutáveis.
- Tipos imutáveis : Número (número), String (string), Tupla (tupla) [todos os tipos de contêiner, exceto tuplas]
- Tipos de variáveis : Lista (lista), Dicionário (dicionário), Conjunto (coleção) [tipo de container Fighter]
- Tipos de não contêiner : Número (número), String (string) [ambos os tipos imutáveis]
- Tipo de contêiner : lista (lista), dicionário (dicionário), tupla (tupla) [tipos de variáveis exceto tuplas]
- Para facilitar a compreensão, você pode dar uma olhada no seguinte diagrama esquemático reproduzido de outros.
"Cópia" de tipos imutáveis
Os tipos imutáveis não são tipos de contêineres, exceto tuplas . Eles não são copiados. A cópia usando o módulo de cópia é uma atribuição direta e transferência de endereços de memória.
- Para entender alguns motivos de design para cópia, devemos primeiro resolver o motivo da atribuição direta para obter "cópia"
- PorqueA necessidade de copiar é esperar que as duas variáveis não interfiram uma na outra, e uma nova. O tipo imutável de "modificado" para ter alcançado a independência de ambos (sua "modificação" é recriar uma variável, a nova variável para apontar para o novo objeto, a variável antiga ainda aponta para os objetos antigos). Portanto, não há necessidade de abrir um novo espaço para copiar o mesmo conteúdo, basta apontar diretamente para o mesmo endereço.
- Verificação na figura:
a = "a"
b = a # 直接赋值,进行“拷贝”
print(b is a)
b = "b" # “修改”又是直接赋值了,因为它们无法修改
print(a)
print(b)
print(b is a)
Verdadeiro
a
b
Falso
- Tuplas de tipos imutáveis também são atribuídas diretamente . Mas tuplas com elementos variáveis são especiais , consulte a próxima seção.
-> Portanto, na seguinte cópia do tipo de variável / tipo de contêiner, os subelementos do tipo imutável podem ser atribuídos diretamente e transmitidos ao endereço de memória.
Deve-se notar que a atribuição direta aqui é apontar diretamente os rótulos de variáveis antigos e novos para o mesmo objeto . "Modificar" refere-se a "modificar" um rótulo de variável sem mover para outro rótulo de variável. Para que os dois sejam independentes e não afetem.
Atribuição direta de tipos mutáveis
Acima está a atribuição direta de tipos imutáveis, aqui está uma olhada na atribuição direta de tipos mutáveis. Este é o rótulo da variável apontando para o mesmo objeto. Sempre opere o mesmo objeto e não atenderá aos requisitos de cópia:
(Não quero editar a imagem, apenas entendo o significado. Os tipos de contêiner são variáveis, exceto para tuplas. A "cópia" das tuplas será discutida separadamente)
Cópia profunda de tipo variável e cópia superficial
Suas cópias profundas e superficiais são [ criar um novo objeto ], mas os elementos filhos diretos apontam para pontos diferentes. Aqui, os rótulos de variáveis novos e antigos apontam para dois objetos diferentes ! (A tupla é especial, preste atenção depois)
- Portanto, a modificação futura dessas duas variáveis não interferirá uma na outra! Isso também pode ser simplesmente analógico do diagrama "Atribuição direta de tipo imutável" acima: a variável AB é substituída pelo objeto AB (eles correspondem um ao outro); esses dois objetos são recipientes e apontam para muitas "cadeias".
import copy
aList = ["你", "好", 1, [1, 2, 3]]
bList = copy.copy(aList) # 浅拷贝:拷贝了所有元素的内存地址到一个新list对象里
cList = copy.deepcopy(aList) # 深拷贝:在浅拷贝的基础上,还递归为容器元素创建新对象拷贝内容
Na atribuição direta, usamos os rótulos de variáveis antigos e novos como referência para ver a modificação do conteúdo da variável. Aqui, continuamos a olhar para o rótulo da variável, que aponta para o antigo e o novo objeto container. Quando os elementos do objeto container são de tipo imutável, seguindo a lógica acima mencionada, o objeto recém-criado dá aos elementos do objeto container novos endereços de modo a não se afetarem.
- Cópia superficial, porque o tipo imutável
"你"
,"好"
,1
modificar novos objetos são dadas novo endereço, de modo que a interferência entre os dois, mas modificado sub-list[1, 2, 3]
não irá criar um novo objeto, de modo que este tem sido tanto referência o mesmo, mutuamente influente.
- Cópia superficial no dicionário: Crie dois objetos de dicionário, crie um novo objeto * para a chave , mas copie o endereço de memória do valor e seus valores são compartilhados (você precisa entender o diagrama de memória do dicionário). Se os valores tiverem tipos de variáveis, eles ainda afetarão uns aos outros.
- Um novo objeto é criado para a chave: por exemplo, o dicionário A, B: B é uma cópia superficial de A, se uma chave de B for excluída neste momento, a chave correspondente em A não terá efeito. A independência inicial dos dois dicionários é percebida e a necessidade desse tipo de cópia superficial é percebida.
- Veja o diagrama detalhado no ponto 4. Recomenda-se ler os pontos 1 e 2 primeiro.
- Na cópia profunda, a recursão é executada para criar um novo conteúdo de cópia do objeto para o elemento contêiner. Para que as duas variáveis nunca interfiram uma na outra.
- Cópia profunda no dicionário: novos objetos são criados para chaves e valores (tipos imutáveis ainda estão apenas copiando endereços de memória), e os dois não interferem um no outro.
- Caso especial: tupla
- Tuplas são tipos imutáveis e não podem ser copiados, pois passam endereços de memória .
- O especial é que tuplas com elementos de tipo variável podem ser copiadas profundamente , criar um novo objeto e criar recursivamente um novo objeto para o elemento variável (ainda não tem uma cópia superficial,
copy.copy()
mas também transfere o endereço de memória )
- Depois de compreender as cópias profundas e superficiais da lista acima, não é difícil entender as cópias profundas e superficiais do dicionário por analogia.
- Sobre o teste acima: Omitido. Não se esqueça dos pontos de conhecimento. .
Informação reimpressa
-
Atribuição direta: endereço de memória de passagem
-
Cópia superficial: crie um novo objeto, copie todos os endereços de memória
-
Cópia profunda: crie novos objetos, copie endereços de memória de tipos imutáveis e crie recursivamente novos objetos com tipos de variáveis .
-
A diferença entre cópia profunda e cópia superficial de tuplas imutáveis e listas mutáveis
Aqui, a primeira parte, toda a tupla é atribuição direta imutável, por isso é True
;
a segunda parte, um tipo de cópia variável, uma vs. rasa copiar profundo seu conteúdo é o mesmo que ==
é True
, e eles são cópia novos objetos, de modo que o endereço de memória ==
é False
.
Onde a cópia é usada
Python geralmente usa uma cópia superficial por padrão. Os exemplos a seguir estão esperando para serem adicionados.
tal como:
- Fatias
[:]
usando uma cópia rasa - Parâmetros de palavra-chave:
**extra
cópia superficial é usada, a tecla delete dentro da função não tem efeito sobre o valor original externo, mas o valor do tipo de variável é compartilhado
Referência / Reimpressão de imagem: cópia profunda gráfica do Python e cópia superficial - Projeto Tian Xiao- 博客 园