Seite 1 von 1

tiefe copy eines Objektes einer Klasse erstellen

Verfasst: Donnerstag 3. Mai 2007, 10:51
von ferdi09
Hallo,
wie ich gelernt habe ist das Object einer Klasse eine mutable Variable.
D.h. als Beispiel:

Code: Alles auswählen

>>> class A:
...  def __init__(self):
...     self.i = 5
...
>>> a = A()
>>> b = a
>>> b.i = 6
>>> a.i
6
b = a erzeugt also kein neues Objekt genauso wie bei Listen. So weit so gut. Bei Listen kann ich ja eine tiefe Kopie mittels list1 = list2[:] erstellen.
Wie aber erstelle ich eine Tiefe Kopie eines Objektes einer Klasse?

Mfg
Holger

Verfasst: Donnerstag 3. Mai 2007, 11:00
von BlackJack
``liste[:]`` erzeugt eine flache Kopie und keine tiefe Kopie.

Flache oder tiefe Kopien von (fast) beliebigen Objekten macht man mit den Funktionen im `copy`-Modul. Wobei das etwas ist, was man nicht besonders häufig braucht bzw. wo man sich gut überlegen sollte ob das wirklich die Lösung ist, die man sucht.

Verfasst: Donnerstag 3. Mai 2007, 11:42
von ferdi09
@BlackJack
Hä? Habe ich da etwas Missverstanden?

Code: Alles auswählen

>>> a = [1,2,3]
>>> b = a      # flache Kopie, da b das selbe Objekt wie a ist
>>> a.append(4)
>>> b
[1,2,3,4]
>>> b = a[:]  # tiefe Kopie, da b nicht das selbe Objekt wie a ist
>>> a.append(5)
>>> b
[1,2,3,4]
>>> a
[1,2,3,4,5]
Oder wie definierst du tiefe Kopie?

Verfasst: Donnerstag 3. Mai 2007, 11:52
von EyDu
ferdi09 hat geschrieben:Oder wie definierst du tiefe Kopie?
Eine tiefe Kopie ist, wenn auch alle Unterelemente mit kopiert werden, so dass das alte Objekt und die Kopie vollkommen unabhängig von einander sind.

Probier dies hier mal aus (flache Kopie)

Code: Alles auswählen

a = [1,2]
b = [3,4]
c = [a, b]
print a
print b
print c

cp = c[:]
print a
print b
print c

cp[0].append(3)
print a
print b
print cp
print c #Hier solltest du mehr oder weniger überrascht sein
Tief wäre dann so etwas (auf dieses Beispiel bezogen, mit zwei Ebenen):

Code: Alles auswählen

cp = [a[:], b[:]]

Verfasst: Donnerstag 3. Mai 2007, 12:12
von lunar
ferdi09 hat geschrieben:@BlackJack
Hä? Habe ich da etwas Missverstanden?

Code: Alles auswählen

>>> a = [1,2,3]
>>> b = a      # flache Kopie, da b das selbe Objekt wie a ist
>>> a.append(4)
>>> b
[1,2,3,4]
>>> b = a[:]  # tiefe Kopie, da b nicht das selbe Objekt wie a ist
>>> a.append(5)
>>> b
[1,2,3,4]
>>> a
[1,2,3,4,5]
Oder wie definierst du tiefe Kopie?
Richtigerweise anders als du. Du vollführst in deinem Beispiel eine flache Kopie, die nur die Liste selbst, nicht jedoch die darin enthaltenen Instanzen kopiert, wie es eine tiefe Kopie tun würde.

Verfasst: Donnerstag 3. Mai 2007, 12:26
von joost
Ziemlich wörtliches Zitat von GvR (vergessen von wo):

"Python does't do anything than assigning names to objects."

"=" erzeugt für keinen Typ etwas, das tut ausschließlich der Ausdruck auf der rechten Seite. Für diesen kann dann absolut jeder Name auf der linken Seite stehen (soll insbesondere heißen: auch ein durch frühere Zuweisung anders getypter Variablenname).
___________________
Schlechte Software ist schlimmer als keine Software

Verfasst: Donnerstag 3. Mai 2007, 12:44
von birkenfeld

Code: Alles auswählen

>>> a = [range(2) for x in range(3)]
>>> b = a   # keine Kopie
>>> b = a[:] # flache Kopie
>>> b = copy.copy(a) # das gleiche
>>> b = copy.deepcopy(a) # tiefe Kopie

Verfasst: Donnerstag 3. Mai 2007, 13:35
von EnTeQuAk
Sorry, wenn ich mich einmische... aber...

Code: Alles auswählen

>>> b = a   # keine Kopie
Ist klar. Verändere ich a, verändere ich auch b, da beide die gleiche ID haben und das gleiche sind.

Code: Alles auswählen

>>> b = a[:] # flache Kopie
Ist auch klar. Beide sind komplett unabhängig voneinander. Wen ich verändere, das stört den anderen kaum.

Code: Alles auswählen

>>> b = copy.deepcopy(a) # tiefe Kopie
Macht für mein Auge keinen Unterschied mehr zu einer Flachen Kopie.

Code: Alles auswählen

>>> import copy
>>> a = [1,2]
>>> b = copy.deepcopy(a)
>>> id(b)
9308640
>>> id(a)
9302704
>>> a.append([1,2])
>>> a
[1, 2, [1, 2]]
>>> b
[1, 2]
Oder habe ich jetzt etwas falsch verstanden?
Oder ist das nur ne rein theoretische Sache, ob flach oder tief?

MfG EnTeQuAk

Verfasst: Donnerstag 3. Mai 2007, 13:38
von birkenfeld
Bei einer Liste, die Integers enthält, gibt es keinen Unterschied zwischen einfacher und tiefer Kopie.

Wenn du mein Beispiel genommen hättest, mit geschachtelten Listen, und eine der "Unterlisten" verändert, hättest du den Effekt gesehen.

Verfasst: Donnerstag 3. Mai 2007, 13:40
von Leonidas
EnTeQuAk hat geschrieben:Oder habe ich jetzt etwas falsch verstanden?
Oder ist das nur ne rein theoretische Sache, ob flach oder tief?
Ja, du hast übersehen, dass bei einer tiefen Kopie die Elemente _in_ der Liste auch mitkopiert werden. Ansonsten, bei einer flachen Kopie, sind in der Liste nur Referenzen auf die ursprünglichen Elemente.

Verfasst: Donnerstag 3. Mai 2007, 13:59
von EnTeQuAk
Wenn du mein Beispiel genommen hättest, mit geschachtelten Listen, und eine der "Unterlisten" verändert, hättest du den Effekt gesehen.
Ja, du hast übersehen, dass bei einer tiefen Kopie die Elemente _in_ der Liste auch mitkopiert werden. Ansonsten, bei einer flachen Kopie, sind in der Liste nur Referenzen auf die ursprünglichen Elemente.
Ich habe es nun verstanden ;) Habe eben den Sachverhalt nicht ausprobiert, mit den "unterlisten".

Sehr interessant... ;)


So --> damit übergebe ich wieder dem Threaderöffner das wort ;)

Verfasst: Donnerstag 3. Mai 2007, 14:14
von ferdi09
So --> damit übergebe ich wieder dem Threaderöffner das wor
Ich glaube ich habe es auch begriffen :)
Danke für die Hilfe.