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))
J'obtiens les résultats suivants:
immutable - id(a)==id(a1) True
immutable - id(b)==id(b1) True
mutable - id(c)==id(c1) False
mutable - id(d)==id(d1) False
Si j'effectue une copie profonde:
a1 = copy.deepcopy(a)
b1 = copy.deepcopy(b)
c1 = copy.deepcopy(c)
d1 = copy.deepcopy(d)
les résultats sont les mêmes:
immutable - id(a)==id(a1) True
immutable - id(b)==id(b1) True
mutable - id(c)==id(c1) False
mutable - id(d)==id(d1) False
Si je travaille sur des opérations d'affectation:
a1 = a
b1 = b
c1 = c
d1 = d
alors les résultats sont:
immutable - id(a)==id(a1) True
immutable - id(b)==id(b1) True
mutable - id(c)==id(c1) True
mutable - id(d)==id(d1) True
Quelqu'un peut-il expliquer ce qui fait exactement la différence entre les copies? Est-ce quelque chose lié aux objets mutables et immuables? Si oui, pouvez-vous me l'expliquer?
list_=[[1,2],[3,4]] newlist = list_.copy() list_[0]=[7,8] print(list_) print(newlist)
L'newlist
affichage fixe[[1, 2], [3, 4]]
. Maislist_[0]
c'est une liste qui est mutable.list_[0]
est modifiable, mais vous ne le mutez / modifiez pas. Essayezlist_[0].append(9)
ou à lalist_[0][0] = 7
place.Pour les objets immuables, il n'est pas nécessaire de copier car les données ne changeront jamais, donc Python utilise les mêmes données; les identifiants sont toujours les mêmes. Pour les objets mutables, car ils peuvent potentiellement changer, la copie [superficielle] crée un nouvel objet.
La copie profonde est liée aux structures imbriquées. Si vous avez une liste de listes, alors deepcopy
copies
également en les listes imbriquées, il s'agit donc d'une copie récursive. Avec juste copier, vous avez une nouvelle liste externe, mais les listes internes sont des références.L'affectation n'est pas copiée. Il définit simplement la référence aux anciennes données. Vous devez donc copier pour créer une nouvelle liste avec le même contenu.
la source
With just copy, you have a new outer list but inner lists are references.
Pour les listes internes, celle copiée serait-elle influencée par la liste originale? Je crée une liste de listes commelist_=[[1,2],[3,4]] newlist = list_.copy() list_[0]=[7,8]
et lanewlist
reste la même, donc la liste intérieure est-elle une référence?list_[0][0] = 7
Pour les objets immuables, créer une copie n'a pas beaucoup de sens car ils ne vont pas changer. Pour les objets mutables
assignment
,copy
etdeepcopy
se comporte différemment. Permet de parler de chacun d'eux avec des exemples.Une opération d'assignation affecte simplement la référence de la source à la destination, par exemple:
Désigne maintenant
i
etj
techniquement la même liste. Les deuxi
etj
ont la même adresse mémoire. Toute mise à jour de l'un d'eux sera répercutée sur l'autre. par exemple:D'autre part
copy
etdeepcopy
crée une nouvelle copie de variable. Les modifications apportées à la variable d'origine ne seront donc plus répercutées sur la variable de copie et vice versa. Cependantcopy(shallow copy)
, ne crée pas de copie des objets imbriqués, mais copie simplement la référence des objets imbriqués. Deepcopy copie tous les objets imbriqués de manière récursive.Quelques exemples pour démontrer le comportement de
copy
etdeepcopy
:Exemple de liste plate utilisant
copy
:Exemple de liste imbriquée utilisant
copy
:Exemple de liste plate utilisant
deepcopy
:Exemple de liste imbriquée utilisant
deepcopy
:la source
Voyons dans un exemple graphique comment le code suivant est exécuté:
la source
a, b, c, d, a1, b1, c1 et d1 sont des références à des objets en mémoire, qui sont uniquement identifiés par leurs identifiants.
Une opération d'affectation prend une référence à l'objet en mémoire et affecte cette référence à un nouveau nom.
c=[1,2,3,4]
est une affectation qui crée un nouvel objet de liste contenant ces quatre entiers et affecte la référence à cet objetc
.c1=c
est une affectation qui prend la même référence au même objet et l'affecte àc1
. Étant donné que la liste est modifiable, tout ce qui arrive à cette liste sera visible, que vous y accédiez viac
ouc1
, car ils font tous deux référence au même objet.c1=copy.copy(c)
est une "copie superficielle" qui crée une nouvelle liste et affecte la référence à la nouvelle listec1
.c
pointe toujours vers la liste d'origine. Donc, si vous modifiez la liste àc1
, la liste à laquelle vous vous référezc
ne changera pas.Le concept de copie n'est pas pertinent pour les objets immuables comme les entiers et les chaînes. Comme vous ne pouvez pas modifier ces objets, il n'est jamais nécessaire d'avoir deux copies de la même valeur en mémoire à différents emplacements. Les entiers et les chaînes, ainsi que certains autres objets auxquels le concept de copie ne s'applique pas, sont simplement réaffectés. C'est pourquoi vos exemples avec
a
etb
aboutissent à des identifiants identiques.c1=copy.deepcopy(c)
est une "copie complète", mais elle fonctionne de la même manière qu'une copie superficielle dans cet exemple. Les copies profondes diffèrent des copies superficielles en ce que les copies superficielles feront une nouvelle copie de l'objet lui-même, mais toutes les références à l' intérieur de cet objet ne seront pas elles-mêmes copiées. Dans votre exemple, votre liste ne contient que des entiers (qui sont immuables), et comme nous l'avons vu précédemment, il n'est pas nécessaire de les copier. La partie "profonde" de la copie profonde ne s'applique donc pas. Cependant, considérez cette liste plus complexe:e = [[1, 2],[4, 5, 6],[7, 8, 9]]
Il s'agit d'une liste qui contient d'autres listes (vous pouvez également la décrire comme un tableau à deux dimensions).
Si vous exécutez une "copie superficielle" sur
e
, en la copiante1
, vous constaterez que l'id de la liste change, mais chaque copie de la liste contient des références aux trois mêmes listes - les listes avec des nombres entiers à l'intérieur. Cela signifie que si vous deviez le fairee[0].append(3)
, cee
serait le cas[[1, 2, 3],[4, 5, 6],[7, 8, 9]]
. Mais lee1
serait aussi[[1, 2, 3],[4, 5, 6],[7, 8, 9]]
. D'un autre côté, si vous l'avez fait par la suitee.append([10, 11, 12])
, cee
serait le cas[[1, 2, 3],[4, 5, 6],[7, 8, 9],[10, 11, 12]]
. Maise1
serait toujours[[1, 2, 3],[4, 5, 6],[7, 8, 9]]
. En effet, les listes externes sont des objets distincts qui contiennent initialement chacun trois références à trois listes internes. Si vous modifiez les listes internes, vous pouvez voir ces changements, que vous les consultiez sur une copie ou sur l'autre. Mais si vous modifiez l'une des listes externes comme ci-dessus, alorse
contient trois références aux trois listes d'origine plus une référence à une nouvelle liste. Ete1
ne contient toujours que les trois références originales.Une `` copie en profondeur '' non seulement dupliquerait la liste externe, mais elle irait également à l'intérieur des listes et dupliquerait les listes internes, de sorte que les deux objets résultants ne contiennent aucune des mêmes références (en ce qui concerne les objets mutables) . Si les listes internes avaient d'autres listes (ou d'autres objets tels que des dictionnaires) à l'intérieur, elles seraient également dupliquées. C'est la partie «profonde» de la «copie profonde».
la source
En python, lorsque nous assignons des objets comme list, tuples, dict, etc. à un autre objet généralement avec un signe '=', python crée des copies par référence . Autrement dit, disons que nous avons une liste de liste comme celle-ci:
et nous attribuons une autre liste à cette liste comme:
alors si nous imprimons list2 dans le terminal python, nous obtiendrons ceci:
List1 et list2 pointent tous les deux vers le même emplacement mémoire, toute modification apportée à l'un d'eux entraînera des changements visibles dans les deux objets, c'est-à-dire que les deux objets pointent vers le même emplacement mémoire. Si nous changeons list1 comme ceci:
alors list1 et list2 seront:
Maintenant à la copie peu profonde , lorsque deux objets sont copiés via une copie superficielle, l'objet enfant des deux objets parents fait référence au même emplacement de mémoire, mais toute nouvelle modification dans l'un des objets copiés sera indépendante l'une de l'autre. Comprenons cela avec un petit exemple. Supposons que nous ayons ce petit extrait de code:
remarquez que list2 reste inchangé, mais si nous apportons des modifications aux objets enfants comme:
alors list1 et list2 obtiendront des modifications:
Maintenant, copie profonde permet de créer des objets complètement isolés les uns des autres. Si deux objets sont copiés via Deep Copy, le parent et son enfant pointeront vers un emplacement mémoire différent. Exemple :
remarquez que list2 reste inchangé, mais si nous apportons des modifications aux objets enfants comme:
alors list2 ne sera pas affecté car tous les objets enfants et objets parents pointent vers un emplacement mémoire différent:
J'espère que ça aide.
la source
Le code ci-dessous montre la différence entre l'affectation, la copie superficielle à l'aide de la méthode de copie, la copie superficielle à l'aide de la (tranche) [:] et la copie profonde. L'exemple ci-dessous utilise des listes imbriquées en rendant les différences plus évidentes.
la source
Le GIST à prendre est le suivant: Traiter des listes superficielles (pas de sous-listes, juste des éléments simples) en utilisant une «affectation normale» augmente un «effet secondaire» lorsque vous créez une liste peu profonde, puis vous créez une copie de cette liste en utilisant une «affectation normale» . Cet "effet secondaire" survient lorsque vous modifiez un élément de la liste de copie créée, car il modifie automatiquement les mêmes éléments de la liste d'origine. C'est quand cela
copy
est pratique, car cela ne changera pas les éléments de la liste d'origine lors du changement des éléments de copie.D'un autre côté,
copy
cela a également un "effet secondaire" lorsque vous avez une liste qui contient des listes (sub_lists) et ladeepcopy
résout. Par exemple, si vous créez une grande liste contenant des listes imbriquées (sub_lists) et que vous créez une copie de cette grande liste (la liste d'origine). L '«effet secondaire» se produirait lorsque vous modifiez les sous-listes de la liste de copie, ce qui modifierait automatiquement les sous-listes de la grande liste. Parfois (dans certains projets), vous souhaitez conserver la grande liste (votre liste d'origine) telle qu'elle est sans modification, et tout ce que vous voulez, c'est faire une copie de ses éléments (sub_lists). Pour cela, votre solution est d'utiliserdeepcopy
ce qui va prendre en charge cet "effet secondaire" et en faire une copie sans modifier le contenu d'origine.Les différents comportements
copy
etdeep copy
opérations ne concernent que les objets composés (c'est-à-dire les objets qui contiennent d'autres objets tels que des listes).Voici les différences illustrées dans cet exemple de code simple:
Première
vérifions le
copy
comportement (superficiel), en créant une liste originale et une copie de cette liste:Maintenant, exécutons quelques
print
tests et voyons comment la liste d'origine se comporte par rapport à sa liste de copie:original_list et copy_list ont des adresses différentes
les éléments de original_list et copy_list ont les mêmes adresses
les sous-éléments de original_list et copy_list ont les mêmes adresses
la modification des éléments original_list ne modifie PAS les éléments copy_list
la modification des éléments copy_list ne modifie PAS les éléments original_list
la modification des sous-éléments de la liste d'origine modifie automatiquement les sous-éléments de la liste de copie
la modification des sous-éléments copy_list modifie automatiquement les sous-éléments original_list
Seconde
vérifions comment
deepcopy
se comporte, en faisant la même chose que nous avons fait aveccopy
(création d'une liste originale et d'une copie de cette liste):Maintenant, exécutons quelques
print
tests et voyons comment la liste d'origine se comporte par rapport à sa liste de copie:original_list et copy_list ont des adresses différentes
les éléments de original_list et copy_list ont les mêmes adresses
les sous-éléments de original_list et copy_list ont des adresses différentes
la modification des éléments original_list ne modifie PAS les éléments copy_list
la modification des éléments copy_list ne modifie PAS les éléments original_list
la modification des sous-éléments de la liste d'origine ne modifie PAS les sous-éléments de la copie_liste
la modification des sous-éléments copy_list ne modifie PAS les sous-éléments original_list
la source
Je ne sais pas si cela est mentionné ci-dessus ou non, mais il est très importable de comprendre que .copy () crée une référence à l'objet d'origine. Si vous modifiez l'objet copié - vous modifiez l'objet d'origine. .deepcopy () crée un nouvel objet et effectue une copie réelle de l'objet d'origine vers un nouvel objet. La modification d'un nouvel objet copié en profondeur n'affecte pas l'objet d'origine.
Et oui, .deepcopy () copie récursivement l'objet d'origine, tandis que .copy () crée un objet de référence aux données de premier niveau de l'objet d'origine.
La différence de copie / référencement entre .copy () et .deepcopy () est donc significative.
la source
La copie profonde est liée aux structures imbriquées. Si vous avez une liste de listes, alors Deepcopy copie également les listes imbriquées, il s'agit donc d'une copie récursive. Avec juste copier, vous avez une nouvelle liste externe, mais les listes internes sont des références. L'affectation n'est pas copiée. Pour Ex
Production
[[0, 1, 2, 3, 3], 4, 5] [[0, 1, 2, 3, 3], 4, 5, 3] Méthode de copie copier le contenu de la liste externe vers la nouvelle liste mais la liste interne est toujours la même pour les deux listes, donc si vous apportez des modifications à la liste intérieure de toutes les listes, cela affectera les deux listes.
Mais si vous utilisez Deep Copy, cela créera également une nouvelle instance pour la liste interne.
Production
[0, 1, 2, 3] [[0, 1, 2, 3, 3], 4, 5, 3]
la source
la source
a
n'est pas une copie profonde delst
!