Question Comment copier un dictionnaire et seulement éditer la copie


Quelqu'un pourrait-il me l'expliquer? Cela n'a aucun sens pour moi.

Je copie un dictionnaire dans un autre et édite le deuxième et les deux sont changés. Pourquoi cela arrive-t-il?

>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = dict1
>>> dict2
{'key2': 'value2', 'key1': 'value1'}
>>> dict2["key2"] = "WHY?!"
>>> dict1
{'key2': 'WHY?!', 'key1': 'value1'}

465
2018-03-17 21:07


origine


Réponses:


Python jamais copie implicitement des objets. Lorsque vous définissez dict2 = dict1, vous les faites référence au même objet dict exact, donc lorsque vous le modifiez, toutes les références à cet objet continuent de faire référence à l'objet dans son état actuel.

Si vous voulez copier le dict (ce qui est rare), vous devez le faire explicitement avec

dict2 = dict(dict1)

ou

dict2 = dict1.copy()

544
2018-03-17 21:09



Lorsque vous attribuez dict2 = dict1, vous ne faites pas de copie de dict1, il en résulte dict2 être juste un autre nom pour dict1.

Pour copier les types mutables comme les dictionnaires, utilisez copy / deepcopy du copy module.

import copy

dict2 = copy.deepcopy(dict1)

343
2018-03-17 21:11



>>> x={'a': 1, 'b': {'m': 4, 'n': 5, 'o': 6}, 'c': 3}
>>> u=x.copy()
>>> v=dict(x)
>>> import copy
>>> w=copy.deepcopy(x)
>>> x['a']=10
>>> x
{'a': 10, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
>>> u
{'a': 1, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
>>> v
{'a': 1, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
>>> w
{'a': 1, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
>>> x['b']['m']=40
>>> x
{'a': 10, 'c': 3, 'b': {'m': 40, 'o': 6, 'n': 5}}
>>> u
{'a': 1, 'c': 3, 'b': {'m': 40, 'o': 6, 'n': 5}}
>>> v
{'a': 1, 'c': 3, 'b': {'m': 40, 'o': 6, 'n': 5}}
>>> w
{'a': 1, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}

111
2018-03-12 03:23



Sur python 3.5+, il existe un moyen plus simple d'obtenir une copie superficielle en utilisant l'opérateur ** unpackaging. Défini par Pep 448.

>>>dict1 = {"key1": "value1", "key2": "value2"}
>>>dict2 = {**dict1}
>>>print(dict2)
{'key1': 'value1', 'key2': 'value2'}
>>>dict2["key2"] = "WHY?!"
>>>print(dict1)
{'key1': 'value1', 'key2': 'value2'}
>>>print(dict2)
{'key1': 'value1', 'key2': 'WHY?!'}

** décompresse le dictionnaire dans un nouveau dictionnaire qui est ensuite attribué à dict2.

Nous pouvons également confirmer que chaque dictionnaire a un identifiant distinct.

>>>id(dict1)
 178192816

>>>id(dict2)
 178192600

Si une copie profonde est nécessaire, alors copy.deepcopy () est toujours la voie à suivre.


36
2017-09-12 15:39



Vous pouvez également créer un nouveau dictionnaire avec une compréhension du dictionnaire. Cela évite d'importer une copie.

dout = dict((k,v) for k,v in mydict.items())

Bien sûr, dans python> = 2.7, vous pouvez faire:

dout = {k:v for k,v in mydict.items()}

Mais pour compat. Rétrograde, la meilleure méthode est meilleure.


32
2018-03-06 03:28



Les instructions d'affectation dans Python ne copient pas les objets, elles créent des liaisons entre une cible et un objet.

alors, dict2 = dict1, il en résulte une autre liaison entre dict2et l'objet qui dict1 faire référence à.

si vous voulez copier un dict, vous pouvez utiliser le copy module. Le module de copie a deux interfaces:

copy.copy(x)
Return a shallow copy of x.

copy.deepcopy(x)
Return a deep copy of x.

La différence entre la copie superficielle et profonde ne concerne que les objets composés (objets contenant d'autres objets, tels que des listes ou des instances de classe):

UNE copie superficielle construit un nouvel objet composé puis (dans la mesure du possible) insère des références aux objets trouvés dans l'original.

UNE copie profonde construit un nouvel objet composé puis, récursivement, y insère des copies des objets trouvés dans l'original.

Par exemple, dans python 2.7.9:

>>> import copy
>>> a = [1,2,3,4,['a', 'b']]
>>> b = a
>>> c = copy.copy(a)
>>> d = copy.deepcopy(a)
>>> a.append(5)
>>> a[4].append('c')

et le résultat est:

>>> a
[1, 2, 3, 4, ['a', 'b', 'c'], 5]
>>> b
[1, 2, 3, 4, ['a', 'b', 'c'], 5]
>>> c
[1, 2, 3, 4, ['a', 'b', 'c']]
>>> d
[1, 2, 3, 4, ['a', 'b']]

13
2017-12-10 12:25



Vous pouvez copier et modifier la copie nouvellement construite en une seule fois en appelant dict constructeur avec des arguments de mots-clés supplémentaires:

>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = dict(dict1, key2="WHY?!")
>>> dict1
{'key2': 'value2', 'key1': 'value1'}
>>> dict2
{'key2': 'WHY?!', 'key1': 'value1'}

9
2017-10-25 12:41



Chaque variable en python (des trucs comme dict1 ou str ou __builtins__ est un pointeur vers un "objet" platonique caché à l'intérieur de la machine.

Si vous définissez dict1 = dict2, vous venez de pointer dict1 au même objet (ou emplacement de mémoire, ou toute autre analogie que vous aimez) comme dict2. Maintenant, l'objet référencé par dict1 est le même objet référencé par dict2.

Tu peux vérifier: dict1 is dict2 devrait être True. Aussi, id(dict1) devrait être le même que id(dict2).

Tu veux dict1 = copy(dict2), ou dict1 = deepcopy(dict2).

La différence entre copy et deepcopy? deepcopy fera en sorte que les éléments de dict2(l'avez-vous indiqué sur une liste?) sont également des copies.

Je n'utilise pas deepcopy beaucoup - il est généralement peu pratique d'écrire du code qui en a besoin (à mon avis).


7
2018-03-17 23:57



dict2 = dict1 ne copie pas le dictionnaire. Il vous donne simplement une deuxième manière au programmeur (dict2) se référer au même dictionnaire.


6
2018-03-17 21:09