Copy und keine Referenz eines Objekt in eine liste speichern

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
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Code: Alles auswählen

class foo(object):
    def __init__(self, bar):
        self.bar = bar

li = []
f = foo(1)
li.append(f)
f.bar = 2
li.append(f)

print li[0].bar
print li[1].bar
output:
2
2

Code: Alles auswählen

import copy

class foo(object):
    def __init__(self, bar):
        self.bar = bar
    
    def __getslice__(self, a, b):
        return copy.copy(self)

li = []
f = foo(1)
li.append(f[:])
f.bar = 2
li.append(f[:])

print li[0].bar
print li[1].bar
output:
1
2

Geht das auch eleganter? Ich wollte gerne das ein Objekt von "foo" nicht als Referenz sondern als Kopie in die Liste gepusht wird. Die Methode mit Überladung von "getslice" und "copy.copy" erscheint mir da nicht wirklich gut, da mein eigentliches Objekt sich nicht wie eine Liste verhält.

lg
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Oder wäre das sinnvoll eine Methode mit den Namen "getcopy" in "foo" zu implementieren?
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Das ist keine Referenz, du hast das Objekt nur an einen neuen Namen (in dem Fall Attribut) gebunden. Kopien von Objekten erstellt man wie gesagt mit copy.copy() bzw d.copy() im falle Dict, oder l[:] für listen. Diese Kopien sind hole Kopien. Die darin gespeicherten Objekte werden nicht mitkopiert.
TUFKAB – the user formerly known as blackbird
Benutzeravatar
sunmountain
User
Beiträge: 89
Registriert: Montag 13. März 2006, 17:18

mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

sunmountain hat geschrieben:Python ist an dieser Stelle etwas "krumm".
Wieso krumm?
TUFKAB – the user formerly known as blackbird
Benutzeravatar
sunmountain
User
Beiträge: 89
Registriert: Montag 13. März 2006, 17:18

... weil sich die Semantik für das Erstellen einer Kopie eines
Objektes unterscheidet.
Bei Ruby ist es immer o.clone oder o.dup, bei Python kommt
hier leider die aus der Historie herraus (noch) bestehenden Unterschiede
zwischen Typen und Klassen zum Vorschein.
Aber in meiner täglichen Praxis habe ich sehr selten mit sowas zu kämpfen,
wenngleich es eigentlich auch einfacher ginge - vielleicht in Python 3.0 ?

Siehe auch:
http://www.faqs.org/faqs/python-faq/part1/
Topic 4.38

Wenn Python eine vollständige und konsistente Klassenhierarchie hat,
wird das wohl auch gehen.
BlackJack

sunmountain hat geschrieben:... weil sich die Semantik für das Erstellen einer Kopie eines
Objektes unterscheidet.
Unterscheidet von *was*!?
Bei Ruby ist es immer o.clone oder o.dup, bei Python kommt
hier leider die aus der Historie herraus (noch) bestehenden Unterschiede
zwischen Typen und Klassen zum Vorschein.
In Python kannst Du neben den "historischen" Möglichkeiten immer `copy.copy()` benutzen.
Wenn Python eine vollständige und konsistente Klassenhierarchie hat, wird das wohl auch gehen.
Um $GOTTES willen, hoffentlich kommt so eine Hierarchie nie. "Flat is better than nested". Und was für einen Unterschied macht das für's kopieren von Objekten?
Benutzeravatar
sunmountain
User
Beiträge: 89
Registriert: Montag 13. März 2006, 17:18

Erste Ansätze in Richtung "nested" wurden mit 2.5 und den Exceptions schon gemacht.
Alle Objekte/Klassen sollten von "object" erben, und einige Zentrale
Dinge (z.B. copy/clone) können so elegant und _vor allem konsistent_ geregelt werden (z.B. durch eventuelles Überladen).
Einer der Gründe, warum ich Ruby so elegant finde (und auch andere).
Typen und Klassen sollten sich in der reinen Lehre nicht unterscheiden.
Python wird irgendwann rein-OO sein, da bin ich mir sicher.
Ein "flat" Ansatz bedeutet m.b.M.n immer, das jemand etwas nicht richtig zu Ende gedacht hat - letzten Endes läuft es nähmlich auf Redundanzen hinaus.
BlackJack

sunmountain hat geschrieben:Alle Objekte/Klassen sollten von "object" erben, und einige Zentrale
Dinge (z.B. copy/clone) können so elegant und _vor allem konsistent_ geregelt werden (z.B. durch eventuelles Überladen).
Was ist denn an der jetzigen Situation inkonsistent? Es gibt `copy.copy()`.
Python wird irgendwann rein-OO sein, da bin ich mir sicher.
Ist es doch jetzt schon.
Ein "flat" Ansatz bedeutet m.b.M.n immer, das jemand etwas nicht richtig zu Ende gedacht hat - letzten Endes läuft es nähmlich auf Redundanzen hinaus.
Wieso das? Und wo sind die bei Python?
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Ich hab so irgendwie das Gefühl du (sunmountain) hast das Copy Protokoll nicht verstanden :roll:

Und was haben Typen und Klassen mit Kopieren zu tun?
TUFKAB – the user formerly known as blackbird
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

blackbird hat geschrieben:Das ist keine Referenz, du hast das Objekt nur an einen neuen Namen (in dem Fall Attribut) gebunden.
Nö.
XtraNine hat geschrieben:

Code: Alles auswählen

class foo(object):
    def __init__(self, bar):
        self.bar = bar

li = []
f = foo(1)
li.append(f)
f.bar = 2
li.append(f)

print li[0].bar
print li[1].bar
output:
2
2
"f" wird ja nicht als Kopie in die Liste"li" gepusht sondern das "Element" in der liste enthält eine Referenz zu "f". Das heißt, wenn ich ein Attribut (".bar") von "f" ändere, da wird auch Automatisch "li[0].bar" mit den neune Wert geändert, weil es eben kein Kopie sondern eine Referenz zu "f" enthält.
Ich meine, das prob an sich habe ich ja mit "copy.copy(self)" (wie man im ersten post erkennen kann) ja gelöst in dem ich...

Code: Alles auswählen

def __getslice__(self, a, b):
        return copy.copy(self)
implementiert habe.

Aber die Methode "[:]" zu benutzen (was ja eigentlich für listen gedacht ist), finde ich nicht besonders sauber. Hätte ja sein können das Python vielleicht so was ähnliches wie " __getcopy()__" hat oder so.

Naja, egal. Ich mache das dann wie gehabt so:

Code: Alles auswählen

li.append(foo(1))
li.append(foo(2))
Diese Kopien sind hole Kopien. Die darin gespeicherten Objekte werden nicht mitkopiert.
Hmm, naja ist zwar kein "deepcopy()" aber ich hatte damit bisher keine Probleme das die Elemente nicht richtig waren :?

lg

P.S.: @sunmountain: Was bitte ist Python wenn nicht OOP? o0
BlackJack

XtraNine hat geschrieben:Aber die Methode "[:]" zu benutzen (was ja eigentlich für listen gedacht ist), finde ich nicht besonders sauber. Hätte ja sein können das Python vielleicht so was ähnliches wie " __getcopy()__" hat oder so.
Es gibt `copy.copy()`, warum benutzt Du das nicht einfach direkt, ohne diesen komischen Umweg über's slicen!?

Code: Alles auswählen

li.append(copy.copy(f))
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

XtraNine hat geschrieben:Aber die Methode "[:]" zu benutzen (was ja eigentlich für listen gedacht ist), finde ich nicht besonders sauber. Hätte ja sein können das Python vielleicht so was ähnliches wie " __getcopy()__" hat oder so.
Hat es auch. Das heißt `__copy__` und `__deepcopy__`. Und jetzt rate mal welche Funktionen das aufrufen. Richtig. copy.copy() und copy.deepcopy() :D
TUFKAB – the user formerly known as blackbird
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

blackbird hat geschrieben: Und jetzt rate mal welche Funktionen das aufrufen. Richtig. copy.copy() und copy.deepcopy() :D
Hehe :D Ok ^^

Thx :)

lg
xtra
Antworten