630 Stimmen

Tiefe Kopie eines Diktats in Python

Ich möchte eine tiefe Kopie eines dict in Python. Leider ist die .deepcopy() Methode gibt es nicht für die dict . Wie kann ich das tun?

>>> my_dict = {'a': [1, 2, 3], 'b': [4, 5, 6]}
>>> my_copy = my_dict.deepcopy()
Traceback (most recent calll last):
  File "<stdin>", line 1, in <module>
AttributeError: 'dict' object has no attribute 'deepcopy'
>>> my_copy = my_dict.copy()
>>> my_dict['a'][2] = 7
>>> my_copy['a'][2]
7

Die letzte Zeile sollte lauten 3 .

Ich möchte, dass die Änderungen in my_dict den Snapshot nicht beeinträchtigen my_copy .

Wie kann ich das tun? Die Lösung sollte mit Python 3.x kompatibel sein.

878voto

Lasse V. Karlsen Punkte 364542

Wie wäre es damit:

import copy
d = { ... }
d2 = copy.deepcopy(d)

Python 2 oder 3:

Python 3.2 (r32:88445, Feb 20 2011, 21:30:00) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import copy
>>> my_dict = {'a': [1, 2, 3], 'b': [4, 5, 6]}
>>> my_copy = copy.deepcopy(my_dict)
>>> my_dict['a'][2] = 7
>>> my_copy['a'][2]
3
>>>

75voto

theBuzzyCoder Punkte 2394

dict.copy() ist eine oberflächliche Kopierfunktion für das Wörterbuch
id ist eine eingebaute Funktion, die Ihnen die Adresse der Variablen

Zunächst müssen Sie verstehen, "warum dieses spezielle Problem auftritt".

In [1]: my_dict = {'a': [1, 2, 3], 'b': [4, 5, 6]}

In [2]: my_copy = my_dict.copy()

In [3]: id(my_dict)
Out[3]: 140190444167808

In [4]: id(my_copy)
Out[4]: 140190444170328

In [5]: id(my_copy['a'])
Out[5]: 140190444024104

In [6]: id(my_dict['a'])
Out[6]: 140190444024104

Die Adresse der Liste, die in beiden Dicts für den Schlüssel "a" vorhanden ist, verweist auf dieselbe Stelle.
Wenn Sie also den Wert der Liste in my_dict ändern, ändert sich auch die Liste in my_copy.


Lösung für die in der Frage genannte Datenstruktur:

In [7]: my_copy = {key: value[:] for key, value in my_dict.items()}

In [8]: id(my_copy['a'])
Out[8]: 140190444024176

Oder Sie können, wie oben erwähnt, Deepcopy verwenden.

74voto

xpros Punkte 1836

Python 3.x

from copy import deepcopy

my_dict = {'one': 1, 'two': 2}
new_dict_deepcopy = deepcopy(my_dict)

Ohne Deepcopy bin ich nicht in der Lage, das Hostnamen-Wörterbuch aus meinem Domänen-Wörterbuch zu entfernen.

Ohne Deepcopy erhalte ich den folgenden Fehler:

"RuntimeError: dictionary changed size during iteration"

...wenn ich versuche, das gewünschte Element aus meinem Wörterbuch innerhalb eines anderen Wörterbuchs zu entfernen.

import socket
import xml.etree.ElementTree as ET
from copy import deepcopy

domain ist ein Wörterbuchobjekt

def remove_hostname(domain, hostname):
    domain_copy = deepcopy(domain)
    for domains, hosts in domain_copy.items():
        for host, port in hosts.items():
           if host == hostname:
                del domain[domains][host]
    return domain

Beispielhafte Ausgabe: [orginal]domains = {'localdomain': {'localhost': {'all': '4000'}}}

[new]domains = {'localdomain': {} }}

Was hier also vor sich geht, ist, dass ich über eine Kopie eines Wörterbuchs iteriere, anstatt über das Wörterbuch selbst. Mit dieser Methode können Sie Elemente nach Bedarf entfernen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X