Verweis auf verschiedene Objekte

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
asfriendsrust
User
Beiträge: 4
Registriert: Freitag 14. Januar 2011, 14:17

hallo leute
ich zweifle gerade mal wieder an meinem verstand: ich möchte für zwei verschiedene thermodynamische zustände jeweils die dazugehörigen stoffwerte berechnen. dazu habe ich die klasse "equal" definiert:

class equal():
pass

nun werden in dieser klasse die verschiedenen stoffwerte wie folgt abgespeichert:
equal.rho=rho
equal.u=...
.
.
.

da einige iterationsschritte für die jeweiligen berechnungen notwendig sind und ich sonst ein bisschen was umschreiben müsste, wobei ich mich schon verhaspelt habe, möchte ich auch die stoffwerte des anderen zustandes in equal speichern. dazu wurden die werte des ersten zustandes anderswo gespeichert(die klasse equali wurde vorher genauso definiert):

equali=equal

für den zweiten zustand ändern sich dann natürlich die einzelnen instanzen von equal, die dan ebenso in einer anderen klasse, nämlich equale gespeichert werden. ändert man jetzt die rechenvariable rho, dann hat das rückwirkungen auf equali.rho und equale.rho, alle drei sind gleich und haben auch die gleiche ID..
nur wenn ich nach ausführung des gesamten skriptes an rho rumspiele bleiben die anderen beiden werte davon unberührt.
ich habs auch schon versucht, so wie auf der folgenden seite unter 12.8 dargestellt zu machen:
http://www.rg16.asn-wien.ac.at/~python/ ... /kap12.htm

also

equali=copy.deepcopy(equal)

bringt aber rein gar nichts..

weiß jemand rat? oder kanns mir genauer erklären, ich habs wohl einfach nur nicht ganz verstanden
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Ohne wirklich (lauffähigen) Beispiel-Code kann man dazu schwerlich etwas genaues sagen. Prinzipiell hast Du ja schon erkannt, dass beim Binden eines Objektes an einen neuen Namen keine Kopie erstellt wird und man dieses explizit über das copy-Modul erledigen muss.

Ich kapiere den Zusammenhang zwischen Deiner Klasse und den Zuständen aus dem bischen Code auch überhaupt nicht. Wozu da eine Klasse? Und zudem meinst Du vielfach eher "Objekt", denn Klasse. Eine Klasse ist zwar in Python auch ein Objekt, aber Du meinst ja eine Instanz dieser Klasse.

Wieso erstellst Du nicht einfach für jeden Zustand eine neues Objekt der Klasse?
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
asfriendsrust
User
Beiträge: 4
Registriert: Freitag 14. Januar 2011, 14:17

Hyperion hat geschrieben:Ohne wirklich (lauffähigen) Beispiel-Code kann man dazu schwerlich etwas genaues sagen. Prinzipiell hast Du ja schon erkannt, dass beim Binden eines Objektes an einen neuen Namen keine Kopie erstellt wird und man dieses explizit über das copy-Modul erledigen muss.
glaube mir, wenn ich den hier rein schreiben würde, würde man überhaupt nix mehr verstehen..
Hyperion hat geschrieben: Ich kapiere den Zusammenhang zwischen Deiner Klasse und den Zuständen aus dem bischen Code auch überhaupt nicht. Wozu da eine Klasse? Und zudem meinst Du vielfach eher "Objekt", denn Klasse. Eine Klasse ist zwar in Python auch ein Objekt, aber Du meinst ja eine Instanz dieser Klasse.
Wieso erstellst Du nicht einfach für jeden Zustand eine neues Objekt der Klasse?
du merkst schon, ich habe im prinzip keine ahnung. und bin ein grausiger programmeirer. im prinzip hab ich das auch nur halb verstanden und dann irgendwas versucht, was dann bezüglich speicherung funktioniert hat.

also könnte man es so machen:

zustand1=equal()
zustand1.rho=...
zustand1.u=...

mit "zustand1" als objekt der klasse "equal" mit den attributen rho, u usw.
und für zustand 2 dann äquivalent?


ändert das was an meinem ursprünglichen problem? (prinzipiell ist meine vorgehensweise also richtig?) die kopplung tritt doch sicherlich trotzdem noch auf. oder gibt's da ganz andere möglichkeiten.

edit: um das problem mal zu vereinfachen:
ich hab das ganze mal direkt in shell ausführen lassen.

import copy
a=5
b=copy.deepcopy(a)

und trotzdem ist die ID jeweils gleich. das passt doch überhaupt nicht mit der beschreibung unter 12.8 aus obigem link zusammen..
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Kann ich so nicht nachvollziehen:

Code: Alles auswählen

In [1]: class Foo(object):
   ...:     pass
   ...: 

In [3]: f = Foo()

In [4]: f.bar = "Hallo Welt"

In [5]: f.x = 42

In [6]: f
Out[6]: <__main__.Foo object at 0x9b2560c>

In [7]: import copy

In [8]: f_copy = copy.copy(f)

In [9]: f_copy
Out[9]: <__main__.Foo object at 0x9b52cac>

In [10]: f is f_copy
Out[10]: False
Dir sollte ja auch eigentlich ein copy() reichen, es sei denn Du hast in Deinem Objekt noch Listen o.ä. (wird ja auch so in der Doku beschrieben)

Ansonsten: Wozu benötigst Du die Kopie? Willst Du Dir den Zustand zu einem bestimmten Zeitpunkt merken, um damit später weiterarbeiten zu können?

Wenn nein, dann erstelle Dir doch immer ein neues Objekt!?!

Nebenbei sollte man nie Namen durchnummerieren; das zeugt davon, dass man lieber eine Liste o.ä. verwenden will:

Code: Alles auswählen

In [11]: states = []

In [12]: states.append(Foo())
                                                                                                                                                                      
In [13]: states.append(Foo())
                                                                                                                                                                      
In [14]: states                                                                                                                                                       
Out[14]: [<__main__.Foo object at 0x9bac04c>, <__main__.Foo object at 0x9bac0ac>]                                                                                     
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
asfriendsrust
User
Beiträge: 4
Registriert: Freitag 14. Januar 2011, 14:17

Hyperion hat geschrieben:Kann ich so nicht nachvollziehen:

Code: Alles auswählen

In [1]: class Foo(object):
   ...:     pass
   ...: 

In [3]: f = Foo()

In [4]: f.bar = "Hallo Welt"

In [5]: f.x = 42

In [6]: f
Out[6]: <__main__.Foo object at 0x9b2560c>

In [7]: import copy

In [8]: f_copy = copy.copy(f)

In [9]: f_copy
Out[9]: <__main__.Foo object at 0x9b52cac>

In [10]: f is f_copy
Out[10]: False
das funktioniert bei mir auch, wie ich gerade feststelle. aber beim datentyp int funtionierts trotzdem nicht. aber das sollte egal sein.

muss ich also mal gucken, woran es sont liegen kann..
Hyperion hat geschrieben: Ansonsten: Wozu benötigst Du die Kopie? Willst Du Dir den Zustand zu einem bestimmten Zeitpunkt merken, um damit später weiterarbeiten zu können?
genau das. es geht um mischungen realer gase.
Hyperion hat geschrieben: Nebenbei sollte man nie Namen durchnummerieren; das zeugt davon, dass man lieber eine Liste o.ä. verwenden will:
das war auch nur zur vereinfachung. im code ist das nicht nummeriert, sondern mit buchstabdne versehen. bei nummerierung würd ich mit den zuständen durcheinander kommen.
Rekrul
User
Beiträge: 78
Registriert: Dienstag 7. Dezember 2010, 16:23

import copy
a=5
b=copy.deepcopy(a)
Macht meines Wissens nach nichts anderes als:

Code: Alles auswählen

a=5
b=a
Dein Beispiel funktioniert so nicht. Ich vermute einfach mal du testest die "id" mit a == b (weil das so in deinem Link gemacht wird). Das funktioniert bei int aber nicht so, da hier der Wert verglichen wird. Google am besten mal nach den Schlagwörtern 'copy by reference' und 'copy by value'.

Aber zu deinem Problem:
Wenn ich dich richtig verstanden habe geht es dir darum Zwischenergebnisse aus einer iterativen Rechnung zu merken. Rho und u? Brauchst du dafür wirklich eine Klasse? Wäre ein Dictionary nicht besser geeignet?

Code: Alles auswählen

equal = {'rho' : ... , 'u' : ...}
Dict musst du dann auch wieder mit deepcopy / copy kopieren, denn mit einer einfachen Zuweisung kopierst du lediglich den Verweis auf dein dictionary. Wenn du nun verschiedene "Zustände" in equal Abspeichern möchtest wäre vielleicht folgende möglichkeit für die interesant:

Code: Alles auswählen

equal = {'zustand1': {'rho' : ... , 'u' : ...}, 'zustand2': {'rho' : ... , 'u' : ...}}
So haben auch deine Zustände Name und keine Zahlen ....
Auf einen Wert im Dictionary kannst du mit eqal['zustand1']['u'] zugreifen.
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

Rekrul hat geschrieben:

Code: Alles auswählen

import copy
a=5
b=copy.deepcopy(a)
Macht meines Wissens nach nichts anderes als:

Code: Alles auswählen

a=5
b=a
Nein. Es liegt an CPython, weil der Zugriff auf kleine Zahlen optimiert wird, sodass alle Namen, die auf das Objekt 5 zeigen, auf das *identische* (nicht nur gleiche) Objekt zeigen. Hier ist ein bisschen Code zur Verdeutlichung:

Code: Alles auswählen

>>> a = 5
>>> b = 5
>>> id(a)
8452440
>>> id(b)
8452440
>>> c = 99999999999999999999
>>> d = 99999999999999999999
>>> id(c)
20725368
>>> id(d)
20725104
asfriendsrust
User
Beiträge: 4
Registriert: Freitag 14. Januar 2011, 14:17

danke für die hilfe!
die ursprüngliche vermutung war wohl nicht die ursache meines problems. ich habe offenbar funktionen, klassen und objekte völlig bunt zusammengewürfelt.
das programm gleicht inzwischen eher einer messi-wohnung als einem durchdachten algorithmus. ich war nur ziemlich davon überzeugt, es liege an der zuweisung auf gleiche identitäten. woran es lag, weiß ich nicht, es funktioniert jetzt aber, ich werde das programm aber wahrscheinlich nochmal neu schreiben, fehler sind bei erweiterungen einfach unauffindbar.

die sache mit den zugriffen auf identische kleine zahlen hat zusätzlich verwirrt..
Antworten