dict.fromkeys verändert alle Elemente

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Thuught
User
Beiträge: 28
Registriert: Mittwoch 3. Dezember 2008, 12:19

Hallo,
ich hätte eine Frage zur Funktion fromkeys:

Code: Alles auswählen

alist=["a","b","c","d"]
d=dict.fromkeys(alist,{"foo":12})
for i in d.iteritems():print i
#=================================
# ('a', {'foo': 12})
# ('c', {'foo': 12})
# ('b', {'foo': 12})
# ('d', {'foo': 12})
#=================================
d["a"]["fuu"]=21
for i in d.iteritems():print i
#=================================
# ('a', {'foo': 12, 'fuu': 21})
# ('c', {'foo': 12, 'fuu': 21})
# ('b', {'foo': 12, 'fuu': 21})
# ('d', {'foo': 12, 'fuu': 21})
#=================================
Wieso unifiziert er alle Werte und wie kann ich das verhindern?
Benutzeravatar
b.esser-wisser
User
Beiträge: 272
Registriert: Freitag 20. Februar 2009, 14:21
Wohnort: Bundeshauptstadt B.

Probiers mit 'nem generator:

Code: Alles auswählen

>>> d = dict(( (c, {"foo":42}) for c in "abcd"))
>>> d["a"] is d["b"]
False
... Python kopiert Objekte nie automatisch, aber das fällt erst bei veränderbaren ('mutable') Objekten auf.

hth, Jörg
Wir haben schon 10% vom 21. Jahrhundert hinter uns!
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Es werden in Python keine Kopien implizit erstellt, sondern immer mit Referenzen gearbeitet. Wenn du eine Kopie möchtest, dann musst du diese explizit erzeugen.

In deinem Fall hast du also fünf Referenzen auf dein Dictionary. Da dieses mutable ist, werden Änderungen an jeder Referenz sichtbar, da diese immer noch das selbe Objekt referenzieren, nur dass dieses seinen Wert geändert hat.

Um das zu lösen musst du zu jeden Schlüssel einen neuen Wert erzeugen. Mach also einfach eine Schleife draus:

Code: Alles auswählen

>>> alist=["a","b","c","d"]
>>> d = {}
>>> for elem in alist:
	d[elem] = {"foo":12}

	
>>> d["a"]["bar"] = 42
>>> d["a"]
{'foo': 12, 'bar': 42}
>>> d["b"]
{'foo': 12}
Oder einen einfachen Generator.
Das Leben ist wie ein Tennisball.
Thuught
User
Beiträge: 28
Registriert: Mittwoch 3. Dezember 2008, 12:19

Das mit den Referenzen war mir nie so bewusst. Gut zu wissen.
Gibt es denn eine Möglichkeit bei Zuweisungen eine Kopie von Objekten zu erzwingen?
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

b.esser-wisser hat geschrieben:Python kopiert Objekte nie automatisch
Irgendwie fällt das momentan unter die Top-Aussagen im Forum. ;)
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Thuught hat geschrieben:Gibt es denn eine Möglichkeit bei Zuweisungen eine Kopie von Objekten zu erzwingen?
Ja, indem du ``copy.copy`` nutzt.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten