Seite 1 von 1

Copy und keine Referenz eines Objekt in eine liste speichern

Verfasst: Freitag 8. Dezember 2006, 12:30
von sape

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

Verfasst: Freitag 8. Dezember 2006, 12:32
von sape
Oder wäre das sinnvoll eine Methode mit den Namen "getcopy" in "foo" zu implementieren?

Verfasst: Freitag 8. Dezember 2006, 13:25
von mitsuhiko
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.

siehe auch

Verfasst: Freitag 8. Dezember 2006, 13:52
von sunmountain

Re: siehe auch

Verfasst: Freitag 8. Dezember 2006, 13:55
von mitsuhiko
sunmountain hat geschrieben:Python ist an dieser Stelle etwas "krumm".
Wieso krumm?

Krumm deshalb ...

Verfasst: Freitag 8. Dezember 2006, 14:01
von sunmountain
... 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.

Re: Krumm deshalb ...

Verfasst: Freitag 8. Dezember 2006, 14:32
von 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?

flat is better then nested

Verfasst: Freitag 8. Dezember 2006, 15:03
von sunmountain
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.

Re: flat is better then nested

Verfasst: Freitag 8. Dezember 2006, 15:41
von 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?

Verfasst: Freitag 8. Dezember 2006, 16:48
von mitsuhiko
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?

Verfasst: Freitag 8. Dezember 2006, 20:39
von sape
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

Verfasst: Freitag 8. Dezember 2006, 21:28
von 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))

Verfasst: Samstag 9. Dezember 2006, 00:45
von mitsuhiko
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

Verfasst: Samstag 9. Dezember 2006, 17:28
von sape
blackbird hat geschrieben: Und jetzt rate mal welche Funktionen das aufrufen. Richtig. copy.copy() und copy.deepcopy() :D
Hehe :D Ok ^^

Thx :)

lg
xtra