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

Copy und keine Referenz eines Objekt in eine liste speichern

Beitragvon sape » Freitag 8. Dezember 2006, 12:30

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

Beitragvon sape » Freitag 8. Dezember 2006, 12:32

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

Beitragvon mitsuhiko » Freitag 8. Dezember 2006, 13:25

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

siehe auch

Beitragvon sunmountain » Freitag 8. Dezember 2006, 13:52

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

Re: siehe auch

Beitragvon mitsuhiko » Freitag 8. Dezember 2006, 13:55

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

Krumm deshalb ...

Beitragvon sunmountain » Freitag 8. Dezember 2006, 14:01

... 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

Re: Krumm deshalb ...

Beitragvon BlackJack » Freitag 8. Dezember 2006, 14:32

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

flat is better then nested

Beitragvon sunmountain » Freitag 8. Dezember 2006, 15:03

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

Re: flat is better then nested

Beitragvon BlackJack » Freitag 8. Dezember 2006, 15:41

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?
Benutzeravatar
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Beitragvon mitsuhiko » Freitag 8. Dezember 2006, 16:48

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

Beitragvon sape » Freitag 8. Dezember 2006, 20:39

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

Beitragvon BlackJack » Freitag 8. Dezember 2006, 21:28

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))
Benutzeravatar
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Beitragvon mitsuhiko » Samstag 9. Dezember 2006, 00:45

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

Beitragvon sape » Samstag 9. Dezember 2006, 17:28

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

Thx :)

lg
xtra

Wer ist online?

Mitglieder in diesem Forum: Bing [Bot]