tiefe copy eines Objektes einer Klasse erstellen

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
ferdi09
User
Beiträge: 16
Registriert: Donnerstag 18. Januar 2007, 11:23

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
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.
ferdi09
User
Beiträge: 16
Registriert: Donnerstag 18. Januar 2007, 11:23

@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?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

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[:]]
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.
joost
gelöscht
Beiträge: 134
Registriert: Sonntag 29. April 2007, 13:28

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
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

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
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

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
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

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.
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

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.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

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 ;)
ferdi09
User
Beiträge: 16
Registriert: Donnerstag 18. Januar 2007, 11:23

So --> damit übergebe ich wieder dem Threaderöffner das wor
Ich glaube ich habe es auch begriffen :)
Danke für die Hilfe.
Antworten