2009-05-08 10 views
19

Ich habe mich gefragt, wie genau das tut, deep Arbeit in folgendem Zusammenhang:Python Wörterbuch deep

from copy import deepcopy 

def copyExample: 
    self.myDict = {} 
    firstPosition = "First" 
    firstPositionContent = ["first", "primero"] 
    secondPosition = "Second" 
    secondPositionContent = ["second"] 
    self.myDict[firstPosition] = firstPositionContent 
    self.myDict[secondPosition] = secondPositionContent 
    return deepcopy(self.myDict) 

def addExample(self): 
    copy = self.copyExample() 
    copy["Second"].add("segundo") 

Hat sie den Verweis auf den Listen kehre ich im Wörterbuch haben? Oder funktioniert es wie erwartet und kopiere jede Liste in einer neuen Liste mit einer anderen Referenz?

Ich weiß, was eine tiefe Kopie ist (also gibt es keine Notwendigkeit, den Unterschied zwischen tief und flach zu erklären), aber ich frage mich, ob es funktioniert, wie ich es erwarte und daher die Instanzvariable nicht ändern, wenn ich benutze addExample().

+1

Haben drucken Sie die beiden Wörterbücher, um zu sehen, wenn sie anders sind? Was hast du gesehen? Waren sie anders? Wenn ja, hat die Kopie eine neue Liste, zu der Sie ein Element hinzugefügt haben. –

Antwort

15

Die documentation macht es ziemlich klar, dass Sie neue Kopien, keine Referenzen erhalten. Deepcopy erstellt tiefe Kopien für integrierte Typen mit verschiedenen Ausnahmen und Sie können Ihren benutzerdefinierten Objekten benutzerdefinierte Kopieroperationen hinzufügen, um auch für sie tiefe Kopierunterstützung zu erhalten. Wenn Sie sich nicht sicher sind, dann ist Unit-Testing genau das Richtige für Sie.

+0

Ich glaube nicht, dass es eingebaute Typen gibt, es besagt, dass es die auswählbaren Objekte "kopiert" ... Bedeutet das, dass ich eine neue Listenreferenz bekommen würde? – mandel

+7

Deepcopy hat eine kurze Liste von Ausnahmen. Alles andere wird kopiert. "Dieses Modul kopiert keine Typen wie Modul, Methode, Stack-Trace, Stack-Frame, Datei, Socket, Fenster, Array oder ähnliche Typen." Du bekommst eine neue Liste. Kein Verweis auf die Liste, sondern eine neue Liste. Drucke die beiden Wörterbücher aus deinem Beispiel und sieh sie dir an. –

2

Ich weiß, es beantwortet Ihre Frage nicht, aber ich denke, es ist bemerkenswert für Leute, die diese Frage betrachten.

Wenn die Daten, die Sie kopieren, einfach in der Natur sind, ist die Verwendung von decepopy möglicherweise übertrieben. Mit einfach in der Natur meine ich, wenn Ihre Daten als Json darstellbar sind. Lassen Sie mich mit Code veranschaulichen:

Ich habe http://www.json-generator.com/ verwendet, um einige Beispiel-JSON-Daten zu erhalten.

def deepCopyList(inp): 
    for vl in inp: 
     if isinstance(vl, list): 
      yield list(deepCopyList(vl)) 
     elif isinstance(vl, dict): 
      yield deepCopyDict(vl) 

def deepCopyDict(inp): 
    outp = inp.copy() 
    for ky, vl in outp.iteritems(): 
     if isinstance(vl, dict): 
      outp[ky] = deepCopyDict(vl)  
     elif isinstance(vl, list): 
      outp[ky] = list(deepCopyList(vl)) 
    return outp 

def simpleDeepCopy(inp): 
    if isinstance(inp, dict): 
     return deepCopyDict(inp) 
    elif isinstance(inp, list): 
     return deepCopyList(inp) 
    else: 
     return inp 

if __name__ == '__main__': 
    import simplejson as json 
    import time 
    from copy import deepcopy 
    fl = open('sample.json', 'r') 
    sample = json.load(fl) 
    start = time.time() 
    for _ in xrange(10000): 
     tmp = simpleDeepCopy(sample) 
    end = time.time() 
    print 'simpleDeepCopy: ' + str(end - start) 
    start = time.time() 
    for _ in xrange(10000): 
     tmp = deepcopy(sample) 
    end = time.time() 
    print 'copy.deepcopy: ' + str(end - start) 

Ausgang:

simpleDeepCopy: 0.0132050514221 
copy.deepcopy: 2.66142916679 

simpleDeepCopy: 0.0128579139709 
copy.deepcopy: 2.60736298561 
+0

"Mit einfach in der Natur meine ich, wenn Ihre Daten als Json darstellbar sind" - das ist eine falsche Aussage: selbst einige einfache, "JSON-fähige" Objekte benötigen '.deepcopy()', um Verweise zu vermeiden. Probieren Sie Folgendes aus: 'a = {1: 'A', 2: ['a', 'b', 'c'], 3: 'Z'}; b = a.copy(); a [2] .append ('d'); print b' – MestreLion

+0

Wenn die Daten als JSON darstellbar sind, warum nicht einfach 'json.loads (json.dumps (data))' ..? – rob