Explication détaillée du mécanisme de copie superficielle, de copie profonde et de référence de Python

高洛峰
Libérer: 2017-03-23 17:43:07
original
1507 Les gens l'ont consulté

J'ai rencontré quelques problèmes cette semaine, et puis je me suis rendu compte que si les connaissances de base n'étaient pas consolidées depuis un moment, il y avait encore des parties oubliées qui devaient encore être révisées, je ferai une note ici pour l'enregistrer

Précédemment
Décrivez d'abord brièvement le problème rencontré. L'exigence est d'écrire les résultats de 2 impressions


详解Python浅拷贝、深拷贝及引用机制
As. vous pouvez voir, a pointe vers un objet liste, en Python, une telle instruction d'affectation signifie en fait que a pointe vers l'adresse mémoire de la liste, ce qui peut être considéré comme un concept de type pointeur.

Et b, notez qu'il enveloppe l'objet a dans une liste et le multiplie par 5, donc b devrait ressembler à une grande liste avec tous les éléments a

Quand a Après l'objet. est ajouté, la signification implicite est que la liste en mémoire a été modifiée, et tous les objets qui font référence à cet objet vont changer

J'imprime l'identifiant de a, Et, en même temps, j'imprime l'identifiant de l'élément a contenu dans l'objet b, afin que vous puissiez voir que dans la liste b, l'identifiant de chaque élément est le même que a


详解Python浅拷贝、深拷贝及引用机制
On peut voir que le L'identifiant (adresse mémoire) de l'objet a est 10892296. Bien que b enveloppe a dans une nouvelle liste, cet élément fait toujours référence à l'objet avec la même adresse. Cela peut être expliqué par la figure suivante


<.>详解Python浅拷贝、深拷贝及引用机制 Après cela, nous avons effectué l'opération d'ajout sur a. Puisque la liste est un objet variable, son adresse mémoire n'a pas changé. Cependant, pour cette adresse dans la mémoire, tous les objets référencés seront modifiés ensemble, ce qui peut être vu. à partir de la moitié inférieure de la ligne de démarcation dans le graphique de test ci-dessus

Cela conduit à un examen du mécanisme de référence de Python et de la copie superficielle et de la copie profonde


Mécanisme de référence de Python


Cas 1 du mécanisme de référence

À partir de l'exemple ci-dessus, nous pouvons voir que python En passant la référence, le résultat final est d'avoir deux objets faire référence au contenu de la même zone dans la mémoire
Regardons donc l'exemple suivant

B passe A, et fait également référence à l'identifiant 17446024 Le contenu de l'adresse et l'identifiant (adresse mémoire) des deux sont exactement les mêmes

Ainsi, grâce à l'opération de A A[0]=3 ou A[3].append(6), il modifiera le contenu de cette mémoire (car la liste est un objet variable, l'adresse mémoire ne changera pas, nous en reparlerons plus tard)

C'est le cas de référence le plus basique (en plus, car A et B pointent tous les deux vers la même adresse mémoire, donc le contenu modifié par B peut également se refléter sur A)




详解Python浅拷贝、深拷贝及引用机制 Cas du mécanisme de référence 2

Regardons un autre cas
En regardant la question, il semble que l'élément 2 sera remplacé par la liste elle-même. Le résultat peut être A=[1,[1,2,3],3]

Mais c'est le cas. pas! ! Vous pouvez voir qu'il y en a une infinité

imbriquées dans la case rouge. Pourquoi ?

En fait, c'est parce que A pointe vers la liste [1,2,3]. Dans cet exemple, seul le deuxième élément de A pointe vers l'objet A lui-même, ce n'est donc que le deuxième élément de R. La structure a changé ! Cependant, A pointe toujours vers cet objet

On peut voir en imprimant l'identifiant de A que son pointage n'a pas changé ! !




Regardez, la direction de A n'a pas changé详解Python浅拷贝、深拷贝及引用机制



Alors si nous voulons obtenir l'effet de sortie final est [ 1, [1,2,3],3], comment devons-nous le faire fonctionner ? 详解Python浅拷贝、深拷贝及引用机制
Ici, nous allons utiliser une copie superficielle. L'utilisation peut être la suivante





详解Python浅拷贝、深拷贝及引用机制 Copie superficielle et copie profonde

Copie superficielle

Parlons maintenant de la copie superficielle et de la copie profonde. La méthode ci-dessus n'effectue en fait qu'une copie superficielle, une copie superficielle, ce qui signifie qu'elle copie l'objet référencé d'origine, mais ne fait plus référence à la même adresse d'objet

Regardez l'exemple ci-dessous. B effectue une copie superficielle via l'opération B = A[:] Vous pouvez voir qu'après la copie superficielle, les adresses mémoire référencées par A et B sont déjà différentes

Cependant, le les adresses de référence des éléments à l’intérieur de A et B sont toujours les mêmes, alors soyez très prudent à ce sujet ! Il y a une différence ! ! !

La différence entre les adresses mémoire de référence de A et B signifie que l'opération que vous effectuez sur B n'affectera pas A.

详解Python浅拷贝、深拷贝及引用机制

Résumé de la copie superficielle :

La copie superficielle peut donc être résumée comme la copie d'une référence, du nouvel objet et de l'original L'objet les références sont distinguées, mais les références d'adresse des éléments internes sont toujours les mêmes

Mais une copie superficielle posera également des problèmes. C'est lorsqu'il y a imbrication. Par exemple, comme vous pouvez le voir dans la situation suivante, j'ai attribué une copie superficielle de A à B, de sorte que les ID (adresses mémoire) de A et B soient différents.

Donc, quand je modifie A[0]=8, B ne sera pas affecté, car A et B sont des références indépendantes, mais il y a une liste imbriquée au milieu [4 ,5,6]

Nous pouvons comprendre cela [4,5,6] comme : A et B se réfèrent toujours l'un à l'autre, c'est-à-dire que pour les seconds éléments de A et B, ils pointent toujours vers la même adresse mémoire A.

De plus, puisque int est un type immuable, après avoir changé A[0] en 8, son adresse de référence changera ! Elle se distingue de la référence de l'élément B[0].

详解Python浅拷贝、深拷贝及引用机制

Copie approfondie

Alors comment faire face à une telle situation ? Vous devez utiliser le module de copie dans le module python

Le module de copie a 2 fonctions

1 : copy.copy (l'objet que vous souhaitez copier) : Il s'agit d'une copie superficielle, et la précédente Les propriétés de l'opération [:] sur la liste sont les mêmes

2 : copy.deepcopy (l'objet que vous souhaitez copier) : Il s'agit d'une copie profonde, sauf qu'elle générera une nouvelle objet tout comme la copie superficielle, et pour les éléments internes, de nouvelles références seront générées pour les séparer indépendamment

Regardez l'exemple ci-dessous. Lorsque vous attribuez une copie complète de A à B, elles peuvent être. dit être complètement indépendant. , que vous modifiiez les éléments immuables dans A ou que vous modifiiez les éléments mutables imbriqués dans A, le résultat n'affectera pas B

Je crois comprendre que la copie profonde peut être appelée copie récursive , il le fera. copiez tous les éléments variables imbriqués, puis référencez-les indépendamment

详解Python浅拷贝、深拷贝及引用机制

Résumé de la copie approfondie :

L'effet de la copie approfondie est le même. comme celui de la copie superficielle. En plus de générer une nouvelle référence à partir de la référence de l'objet, cela vous aidera à séparer tous les éléments imbriqués un par un

Dessiné 2 par moi-même Image pour montrer la différence entre la copie superficielle et la copie superficielle. copie profonde

Il convient de noter que bien qu'après une copie superficielle, l'adresse de référence des éléments immuables dans la liste soit toujours la même, mais comme ce sont des éléments immuables, donc après la modification de tout élément immuable, la référence L'adresse sera nouvelle sans affecter l'adresse de référence d'origine.



详解Python浅拷贝、深拷贝及引用机制

详解Python浅拷贝、深拷贝及引用机制

Résumé

Alors, c'est parti, superficiel copy Et le mécanisme de la copie profonde est fondamentalement compris.

Il y a aussi des circonstances particulières qui doivent être expliquées

Pour les types immuables : int, str, tuple, float et autres éléments, il n'y a pas de copie après leur modification, l'adresse de référence. est directement modifié, comme indiqué ci-dessous

详解Python浅拷贝、深拷贝及引用机制

Cependant, s'il y a des types de variables imbriqués à l'intérieur du type immuable, vous pouvez toujours utiliser la copie complète

详解Python浅拷贝、深拷贝及引用机制

Rappel également, la méthode la plus couramment utilisée est l'affectation directe (ou passage direct de références), comme l'exemple suivant

Il combine a et b Deux éléments variables pointent vers une adresse mémoire en même temps, donc tout changement affectera a et b

详解Python浅拷贝、深拷贝及引用机制

Enfin

type de variable : list , set, dict

types immuables : int, str, float, tuple

méthode de copie superficielle : [:], copy.copy(), utilisez la fonction d'usine (list/dir/set )

Copie approfondie méthode : copy.deepcopy()


Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal