Seite 1 von 1

dictionaries automatisch (hokospokus) überschrieben

Verfasst: Dienstag 28. April 2009, 11:46
von KorFreier
Hallo Leute,

ich hab ein Phänomen, aus dem ich nicht schlau werde und würde mich sehr über eine Erklärung freuen (weil es mir ziemlich mystisch bis unlogisch erscheint):

Ich hab mehrere Dictionaries, mehrdimensional, alle gleich und am Beginn ohne values hinter allen Keys (die sollten separat in Schleifen eingetragen werden).

Jetzt fülle ich eines dieser Dicts mittels einer Schleife auf (in meinem Fall das agpm_out) und ...
- plop - haben alle gleichartigen Dicts die gleiche Füllung , obwohl die "="-Zuweisung oberhalb der Schleife ist???. So hat zum Beispiel das Dict opt_out auch eine Füllung nachdem man die Schleife ausführt.

Der Code sieht so aus:

Code: Alles auswählen

key1 = pinput.keys()
key2 = pinput[key1[0]].keys()
key3 = pinput[key1[0]][key2[0]].keys()
years = pinput[key1[0]][key2[0]][key3[0]].keys()
parameters = pinput[key1[0]][key2[0]][key3[0]][years[0]].keys()

## ------- erstellen des virgin-dictionaries
agpm_out  = {}
agpm_out_wet = {}
agpm_out_dry = {}
agpm_out_nor = {}

for dens in key1:
    opt_out = {}
    for opt in key2:
        ens_out = {}
        for ens in key3:
            year_out = {}
            for year in years:
                para_out = {}
                for para in parameters:
                    para_out[para] = {}
                para_out['agpm_bef'] = {}  # AGPM_BEF is the agpm_end of the year before
                year_out[year]=para_out
            ens_out[ens]= year_out
        opt_out[opt] = ens_out
    agpm_out[dens] = opt_out
agpm_out_wet = agpm_out
agpm_out_dry = agpm_out
agpm_out_nor = agpm_out

## -------- zuordnen der Parameter in das dictionary agpm_out
for dens in key1:
    for opt in key2:
        for ens in key3:
            for year in years[1:]: # funktioniert erst ab dem zweiten jahr, da endwert des vorjahres existieren muss
                for para in parameters:
                    agpm_out[dens][opt][ens][year][para] = pinput[dens][opt][ens][year][para]
                agpm_out[dens][opt][ens][year]['agpm_bef'] = pinput[dens][opt][ens][year-1]['agpm_end']
                # hier wird vorjahreswert zugeordnet
Hinzufügen von...

Code: Alles auswählen

 agpm_out = {}
ändert nichts an dem Phänomen. agpm_out ist dann wieder leer, aber die Geschwisterchen bleiben "schwanger".

Hat jemand eine Idee, um welchen Fehler (ich vermute mal Denkfehler meinerseits :oops: ) handeln könnte? Wäre sehr dankbar...

Verfasst: Dienstag 28. April 2009, 12:04
von b.esser-wisser
Jetzt schreibe 100 mal an die Tafel: "ein '=' macht keine Kopie"! :wink:
Nach

Code: Alles auswählen

agpm_out_wet = agpm_out
agpm_out_dry = agpm_out
agpm_out_nor = agpm_out
sind "agpm_out_wet", "agpm_out_dry", "agpm_out_nor" drei Namen für dasselbe Object (!) - copy.copy(), copy.deepcopy() könnten weiterhelfen.

hth, Jörg

Verfasst: Dienstag 28. April 2009, 12:40
von KorFreier
Vielen Dank für die Antwort,
copy.deepcopy(agpm_out) funktioniert wie gewünscht. :D

Mit der "Strafaufgabe" hab ich daher kein Problem :roll: , aber...

um auszuschließen, dass ein Objekt nur verschiedene Namen trägt, hab ich den "agpm_out = {} - Test" gemacht.

Wenn also alle Objekte darauf reagieren, was ich mit agpm_out mache, warum sind sie dann am Ende nicht leer?

Sprich: Nach welchen Gesetzen läuft das, dass ein "=" verschiedene Sachen machen kann (zuweisen, Objekte gleichsetzen)?

(deine Antwort schreib ich dann auch noch hundert mal dazu, dann haben wir wenigstens einen anständigen Lerneffekt) :wink:

Verfasst: Dienstag 28. April 2009, 12:52
von Rebecca
KorFreier hat geschrieben:"agpm_out = {} - Test" gemacht
Weil du damit nicht das Dict aenderst, auf das agpm_out zeigt, sondern agom_out auf ein neues (leeres) Dict zeigen laesst, waehrend deine anderen Namen noch auf das urspruengliche Dict zeigen.

Wenn du wissen willst, ob du es mit gleichen Objekten zu tun hast, kannst du sie mit is vergleichen oder auch mal id() auf sie anwenden.

Verfasst: Dienstag 28. April 2009, 13:10
von KorFreier
:idea:

Jetzt haben wir dann eine exponentielle Lernkurve. Hab's geschnallt, Dank zusammen.

Code: Alles auswählen

agpm_out is agpm_out_dry


...stellt alles klar und ist ohnehin (und überhaupt) ein Befehl, den ich schon lange benutzen hätte können (um zum Beispiel zu testen, ob neue, schnelle Prgrämmchen immer noch das gleiche Ergebnis erzielen, wie die alten, langsamen).

:)

Vielen Dank zusammen!

Verfasst: Dienstag 28. April 2009, 13:15
von EyDu
KorFreier hat geschrieben:

Code: Alles auswählen

agpm_out is agpm_out_dry


...stellt alles klar und ist ohnehin (und überhaupt) ein Befehl, den ich schon lange benutzen hätte können (um zum Beispiel zu testen, ob neue, schnelle Prgrämmchen immer noch das gleiche Ergebnis erzielen, wie die alten, langsamen)]
"is" überprüft aber nur, ob es sich um das _selbe_ (im Sinn von "an der selben Speicherstelle") Objekt handelt, es prüft nicht auf Gleichheit. Wenn du ein altes und ein neues Ergebnis vergleichen willst, dann musst du "==" benutzen.

Verfasst: Dienstag 28. April 2009, 13:18
von b.esser-wisser
Du solltest auf jeden Fall mal [wiki=Objekte]in's Wiki [/wiki] schauen, der Artikel (bzw. effbots Original ) sind ein absolutes Muss für jeden Python-Quereinsteiger

Verfasst: Dienstag 28. April 2009, 14:23
von KorFreier
Gute Lektüre: Ich hab mir schon so was gedacht, als das Wort "zeigen" erwähnt wurde.

Ab sofort denk ich nur noch in Objekten... :wink:

Verfasst: Dienstag 28. April 2009, 14:26
von DasIch
Dennda hat da mal einen netten Blogpost zu gemacht.