10.1 Alles nach meinem Willen!
Manchmal enthalten deine Objekte viele Referenzen zu verschiedenen Dienstobjekten, die du nicht über das Netzwerk senden willst oder nicht senden kannst: Datei-Referenzen, Datenbanken usw.
Damit Serialisierung auch in solchen Fällen funktioniert, wurde die Möglichkeit erfunden, der Klasse die Steuerung ihrer eigenen Serialisierung zu überlassen. Hierfür werden spezielle Methoden genutzt: __reduce__()
, __getstate__()
, __setstate__()
. Diese Methoden erlauben es anzugeben, wie Objekte serialisiert und wiederhergestellt werden sollen.
Grundlegende Methoden der gesteuerten Serialisierung:
-
__reduce__()
: Gibt an, wie das Objekt serialisiert werden soll. -
__getstate__()
: Gibt den Zustand des Objekts für die Serialisierung zurück. -
__setstate__(self, state)
: Stellt das Objekt aus dem Zustand wieder her.
Im Folgenden erkläre ich diese Methoden detailliert und wie sie zusammen verwendet werden können.
10.2 Die Methode __reduce__()
Die Methode __reduce__()
gibt ein Tupel zurück, das angibt, wie das Objekt serialisiert und deserialisiert werden soll. Das Tupel enthält normalerweise:
- Eine Referenz auf die Funktion oder Klasse, die zur Wiederherstellung des Objekts verwendet wird.
- Ein Tupel von Argumenten für diese Funktion oder Klasse.
- Zusätzlichen Objektzustand (falls erforderlich).
Beispiel:
import pickle
class CustomClass:
def __init__(self, value):
self.value = value
def __reduce__(self):
return (self.__class__, (self.value,))
def __repr__(self):
return f"CustomClass(value={self.value})"
# Objekt erstellen
obj = CustomClass(42)
# Objekt serialisieren
serialized_obj = pickle.dumps(obj)
print("Serialisiertes Objekt:", serialized_obj)
# Objekt deserialisieren
deserialized_obj = pickle.loads(serialized_obj)
print("Deserialisiertes Objekt:", deserialized_obj)
Standardmäßig hat die Funktion __reduce__()
folgendes Verhalten:
class CustomClass:
def __init__(self, value):
self.value = value
def __reduce__(self):
# Klasse definieren
cls = self.__class__
# Konstruktorargumente
args = (self.value,)
# Objektzustand
state = self.__dict__
return (cls, args, state)
Sie gibt ein Tupel zurück, das aus drei Objekten besteht:
Referenz auf die aktuelle Klasse
Konstruktorargumente (Tupel)
Referenz auf den aktuellen Objektzustand
Wenn dieses Verhalten für dich passt, brauchst du __reduce__()
nicht zu überschreiben.
10.3 Lesen und Schreiben von Zuständen
Die Methoden __getstate__()
und __setstate__()
Diese Methoden werden verwendet, um den Zustand des Objekts während der Serialisierung und Deserialisierung zu steuern.
-
__getstate__()
: Gibt den Zustand des Objekts zurück, der serialisiert werden soll. -
__setstate__(self, state)
: Stellt das Objekt aus dem Zustand wieder her.
Beispiel:
Angenommen, wir möchten nicht alle Felder eines Objekts speichern, sondern einige davon ausschließen. Dazu musst du in der Methode __getstate__()
folgendes tun:
- Kopiere den aktuellen Zustand des Objekts (festgelegt durch das Dienstfeld
__dict__
) in eine separate Variable – das Wörterbuchstate
. - Entferne daraus alle Felder, die nicht serialisiert werden sollen.
- Gib das erhaltene Objekt als Ergebnis der Funktion
__getstate__()
zurück.
import pickle
class CustomClass:
def __init__(self, value):
self.value = value
self.internal_state = "internal"
def __getstate__(self):
state = self.__dict__.copy()
del state['internal_state'] # Internen Zustand ausschließen
return state
def __setstate__(self, state):
self.__dict__.update(state)
self.internal_state = "restored internal" # Internen Zustand wiederherstellen
def __repr__(self):
return f"CustomClass(value={self.value}, internal_state={self.internal_state})"
# Objekt erstellen
obj = CustomClass(42)
print("Originalobjekt:", obj)
# Objekt serialisieren
serialized_obj = pickle.dumps(obj)
print("Serialisiertes Objekt:", serialized_obj)
# Objekt deserialisieren
deserialized_obj = pickle.loads(serialized_obj)
print("Deserialisiertes Objekt:", deserialized_obj)
Bei der Deserialisierung, in der Funktion __setstate__()
, machen wir zwei Dinge:
- Aktualisieren den aktuellen Zustand des Objekts mit der Methode
update()
. - Das Feld
internal_state
(und andere nicht serialisierbare Felder) erhalten neue Werte.
GO TO FULL VERSION