Explicação detalhada da atribuição direta do Python, cópia profunda e cópia superficial

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)

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.

Atribuição direta

  • 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:
Atribuição direta de tipos mutáveis

(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.

  1. Cópia superficial, porque o tipo imutável "你", "好", 1modificar 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.
    Insira a descrição da imagem aqui
  • 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.
  1. 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.
    Insira a descrição da imagem aqui
  • 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.
  1. 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 )
  1. 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.

Cópia rasa do dicionárioCópia profunda do dicionário

  1. Sobre o teste acima: Omitido. Não se esqueça dos pontos de conhecimento. .

Informação reimpressa

  1. Atribuição direta: endereço de memória de passagem
    Atribuição direta

  2. Cópia superficial: crie um novo objeto, copie todos os endereços de memória
    Cópia superficial

  3. 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 .
    Cópia profunda!

  4. A diferença entre cópia profunda e cópia superficial de tuplas imutáveis ​​e listas mutá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: **extracó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- 博客 园

Acho que você gosta

Origin blog.csdn.net/zsq8187/article/details/109907066
Recomendado
Clasificación