Hallo,
wenn ich Objekte erstelle, habe ich ja eine Speicheradresse aus dem Arbeitsspeicher, in dem das Objekt liegt. Was mache ich jetzt, wenn ich dieses Objekt richtig abspeichern möchte um es beispielsweise das nächste mal wiederzuverwenden? Zum Beispiel in eine json Datei. Eine Liste könnte ich ja ganz einfach abspeichern, aber wie sieht es aus, wenn ich nur diese Adresse habe? Der Arbeitsspeicher wird ja wieder gelehrt...
Objekte abspeichern
- pillmuncher
- User
- Beiträge: 1530
- Registriert: Samstag 21. März 2009, 22:59
- Wohnort: Pfaffenwinkel
Du hast keine Adresse eines Objekts im Arbeitsspeicher. Python ist nicht C.
Du könntest je eine Funktion definieren, die aus einem Objekt eine dict-Repräsentation erzeugt, und eine die aus einer entsprechenden dict-Repräsentation ein Objekt erzeugt, und diese Funktionen dann verwenden. Das Umwandeln eines dicts in einen JSON-String ist mittels des json-Moduls aus der Standardbibliothek trivial.
Du könntest je eine Funktion definieren, die aus einem Objekt eine dict-Repräsentation erzeugt, und eine die aus einer entsprechenden dict-Repräsentation ein Objekt erzeugt, und diese Funktionen dann verwenden. Das Umwandeln eines dicts in einen JSON-String ist mittels des json-Moduls aus der Standardbibliothek trivial.
In specifications, Murphy's Law supersedes Ohm's.
- __blackjack__
- User
- Beiträge: 14078
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@Loster_Paddel: Übrigens selbst wenn das wie C wäre und man tatsächlich die Speicheradressen von Objekten hätte, könnte man die Speicherinhalte nicht einfach so in eine Datei speichern, denn die Bestandteile eines Objektes sind liegen ja wieder als Speicheradressen und man kann wenn man das wieder laden will, nicht garantieren, dass diese Speicherbereiche dann nicht schon von anderen Objekten belegt sind.
Falls Du über das `pickle`-Modul stolpern solltest, eine kleine Warnung: Das sieht auf den ersten Blick superpraktisch aus, hat aber seine Tücken, weil die gespeicherten Daten von der Package-Struktur abhängig ist und auch Probleme bei Code-Änderungen machen können, denn es werden nur die Daten gespeichert und nicht der Code. Und die Datentypen zu den Daten werden als voll qualifizierte Namen gespeichert. Das Modul ist praktisch für die Datenübertragung oder kurzfristiges speichern von aktuellen Daten, beispielsweise in einem Cache, aber nicht für die langfristige Speicherung von Daten zu empfehlen.
Falls Du über das `pickle`-Modul stolpern solltest, eine kleine Warnung: Das sieht auf den ersten Blick superpraktisch aus, hat aber seine Tücken, weil die gespeicherten Daten von der Package-Struktur abhängig ist und auch Probleme bei Code-Änderungen machen können, denn es werden nur die Daten gespeichert und nicht der Code. Und die Datentypen zu den Daten werden als voll qualifizierte Namen gespeichert. Das Modul ist praktisch für die Datenübertragung oder kurzfristiges speichern von aktuellen Daten, beispielsweise in einem Cache, aber nicht für die langfristige Speicherung von Daten zu empfehlen.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
-
- User
- Beiträge: 39
- Registriert: Samstag 16. April 2022, 20:31
Okay und was ist dann das genau?:
__main__.Moebel object at 0x000002B4430F9FD0>
Wenn es nicht die Adresse fürn Speicher ist...
Und danke erstmal. Das stimmr pickle hab ich schon mal gesehen. Werde mich dann erstmal in die dict-Repräsentation einlesen müssen. Es ist auch noch nicht wtwas was ich bisher gebraucht habe, interessiert mich nur, weil es ja nur eine Frage der Zeit ist, bis man irgendwelche Spieler und damit Objekte abspeichern muss...
__main__.Moebel object at 0x000002B4430F9FD0>
Wenn es nicht die Adresse fürn Speicher ist...
Und danke erstmal. Das stimmr pickle hab ich schon mal gesehen. Werde mich dann erstmal in die dict-Repräsentation einlesen müssen. Es ist auch noch nicht wtwas was ich bisher gebraucht habe, interessiert mich nur, weil es ja nur eine Frage der Zeit ist, bis man irgendwelche Spieler und damit Objekte abspeichern muss...
Grundsätzlich ist das ein Hinweis darauf, das die Klasse keine __str__ bzw __repr__ Funktion besitzt:
Ergibt hier auf dem System:
Und dass du eine Instanz dieser Klasse hast.
Code: Alles auswählen
class SampleClass():
def __init__(self, name):
self.name = name
class SampleClassWithRepr():
def __init__(self, name):
self.name = name
def __repr__(self):
return f"<{self.__class__}: {self.name}>"
def main():
ham = SampleClass("Ham")
print(ham)
spam = SampleClassWithRepr("Spam")
print(spam)
if __name__ == "__main__":
main()
Code: Alles auswählen
<__main__.SampleClass object at 0x000001DBB25FAA00>
<<class '__main__.SampleClassWithRepr'>: Spam>
@Loster_Paddel: Die lange Hexzahl im Rückgabewert von `object.__repr__` ist die `id` des Objektes, keine Speicheradresse. Zum Beispiel sieht das bei mir so aus:
Da wird sehr schnell klar, dass das nicht die Speicheradresse sein kann, weil 673 erstens nicht durch 8 teilbar ist und zweitens die Adresse 673 gar nicht dem Prozess gehört, in dem ich das ausgeführt habe:
0x55d8ba394000 ist die kleinste Adresse, die der Prozess benutzen darf.
Die Eigenschaften der `id` sind:
Code: Alles auswählen
>>>> object.__repr__(42)
'<int object at 0x00000000000002a1>'
>>>> id(42)
673
>>>> hex(id(42))
'0x2a1'
Code: Alles auswählen
$ cat /proc/16334/maps
55d8ba394000-55d8ba395000 r--p 00000000 00:18 27294921 /opt/pypy3/bin/pypy3
[... viele Speicherbereiche, nach Adresse sortiert ...]
7ffc9f40a000-7ffc9f42c000 rw-p 00000000 00:00 0 [stack]
7ffc9f4ec000-7ffc9f4f0000 r--p 00000000 00:00 0 [vvar]
7ffc9f4f0000-7ffc9f4f2000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]
Die Eigenschaften der `id` sind:
Nicht mehr, nicht weniger. Insbesondere steht da nichts von „Speicheradresse“.Dokumentation zu `id` hat geschrieben: Return the “identity” of an object. This is an integer which is guaranteed to be unique and constant for this object during its lifetime. Two objects with non-overlapping lifetimes may have the same id() value.
- __blackjack__
- User
- Beiträge: 14078
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
Ich habe es mal etwas angepasst, so dass es rückwärtskompatibel zu Python 2.7 ist und man es mit Jython ausführen kann:
Testlauf mit CPython:
Testlauf mit PyPy
Testlauf mit Jython:
Bei Jython sieht man deutlich, dass man sich nicht darauf verlassen kann, dass in dem Text etwas steht das eine Speicheradresse ist oder sein könnte, denn wenn man ein weiteres Objekt nach `ham` angelegt hätte, stünde bei dem dort 0x3. Und Objekte sind ganz sicher nicht 1 Byte gross. Es ist nicht einmal sicher, dass dort überhaupt eine Nummer steht, oder das die Hexadezimal angegeben ist, oder eben auch nicht ob das eine Speicheradresse ist oder nicht. Die Darstellung ist Implementierungsdetail. Das einzige was die Dokumentation wirklich ”garantiert”, ist das es entweder eine Zeichenkette ist, mit der man (wahrscheinlich) das Objekt in einem Quelltext schreiben könnte, oder das es in ”spitze Klammern” eingefasst ist und das Objekt in einer Form darstellt, die bei der Fehlersuche nützlich sein kann.
Die Grundimplementierung von `object` in CPython hat den Typnamen und die `id()` als Hex-Zahl in spitzen Klammern. Und die `id()` ist irgendeine Zahl die das Objekt zu einem gegebenen Zeitpunkt eindeutig identifiziert. Das *kann* eine Speicheradresse sein. Aber auch eine künstliche ID wie bei Jython. Was auch immer es ist, man sollte sich nicht auf mehr verlassen, als das der Wert eindeutig ist.
Code: Alles auswählen
#!/usr/bin/env python3
class SampleClass(object):
def __init__(self, name):
self.name = name
class SampleClassWithRepr(object):
def __init__(self, name):
self.name = name
def __repr__(self):
return "<{0.__class__.__name__}: {0.name}>".format(self)
def main():
ham = SampleClass("Ham")
print(ham)
spam = SampleClassWithRepr("Spam")
print(spam)
if __name__ == "__main__":
main()
Code: Alles auswählen
<__main__.SampleClass object at 0x7fe50658cd50>
<SampleClassWithRepr: Spam>
Code: Alles auswählen
<__main__.SampleClass object at 0x00007fa8e2cfdda8>
<SampleClassWithRepr: Spam>
Code: Alles auswählen
<__main__.SampleClass object at 0x2>
<SampleClassWithRepr: Spam>
Die Grundimplementierung von `object` in CPython hat den Typnamen und die `id()` als Hex-Zahl in spitzen Klammern. Und die `id()` ist irgendeine Zahl die das Objekt zu einem gegebenen Zeitpunkt eindeutig identifiziert. Das *kann* eine Speicheradresse sein. Aber auch eine künstliche ID wie bei Jython. Was auch immer es ist, man sollte sich nicht auf mehr verlassen, als das der Wert eindeutig ist.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Nicht mal das: Man darf sich nur auf Eindeutigkeit verlassen, wenn die Objekte, deren IDs man vergleicht, paarweise überlappende Lebenszeiten haben.__blackjack__ hat geschrieben: Sonntag 5. Juni 2022, 18:25 Was auch immer es ist, man sollte sich nicht auf mehr verlassen, als das der Wert eindeutig ist.