10.1 Wszystko będzie po mojemu!
Czasami w twoich obiektach jest przechowywanych wiele odwołań do różnych obiektów pomocniczych, które nie chcesz przesyłać przez sieć, lub których nie można przesyłać przez sieć: odwołania do plików, baz danych itp.
Aby serializacja działała również w takich przypadkach, wymyślono, żeby dać klasie możliwość samodzielnego zarządzania swoją serializacją. Do tego używane są specjalne metody: __reduce__()
, __getstate__()
, __setstate__()
. Te metody pozwalają określić, jak obiekty mają być serializowane i przywracane.
Podstawowe metody zarządzanej serializacji:
-
__reduce__()
: Określa, jak obiekt ma być serializowany. -
__getstate__()
: Zwraca stan obiektu do serializacji. -
__setstate__(self, state)
: Przywraca obiekt ze stanu.
Poniżej opowiem o nich dokładniej i jak ich używać razem.
10.2 Metoda __reduce__()
Metoda __reduce__()
zwraca krotkę, która wskazuje, jak obiekt ma być serializowany i deserializowany. Krotka zazwyczaj zawiera:
- Odwołanie do funkcji lub klasy, która będzie używana do przywrócenia obiektu.
- Krotkę argumentów dla tej funkcji lub klasy.
- Dodatkowy stan obiektu (jeśli to konieczne).
Przykład:
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})"
# Tworzenie obiektu
obj = CustomClass(42)
# Serializacja obiektu
serialized_obj = pickle.dumps(obj)
print("Zserializowany obiekt:", serialized_obj)
# Deserializacja obiektu
deserialized_obj = pickle.loads(serialized_obj)
print("Deserializowany obiekt:", deserialized_obj)
Domyślnie funkcja __reduce__()
ma takie zachowanie:
class CustomClass:
def __init__(self, value):
self.value = value
def __reduce__(self):
# Definicja klasy
cls = self.__class__
# Argumenty konstruktora
args = (self.value,)
# Stan obiektu
state = self.__dict__
return (cls, args, state)
Zwraca ona krotkę składającą się z trzech obiektów:
Odwołanie do bieżącej klasy
Argumenty konstruktora (krotka)
Odwołanie do bieżącego stanu obiektu
Jeśli Ciebie takie zachowanie zadowala — __reduce__()
możesz nie nadpisywać.
10.3 Odczyt i zapis stanu
Metody __getstate__()
i __setstate__()
Te metody stosowane są do zarządzania stanem obiektu podczas serializacji i deserializacji.
-
__getstate__()
: Zwraca stan obiektu, który ma być zserializowany. -
__setstate__(self, state)
: Przywraca obiekt ze stanu.
Przykład:
Załóżmy, że chcemy zachować nie wszystkie pola obiektu, a wykluczyć niektóre z nich. Do tego w metodzie __getstate__()
trzeba:
- Skopiować bieżący stan obiektu (ustawiony w polu pomocniczym
__dict__
) do oddzielnej zmiennej — słownikastate
. - Usunąć z niego wszystkie pola, których nie trzeba serializować.
- Zwrócić uzyskany obiekt jako wynik funkcji
__getstate__()
.
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'] # Wykluczamy wewnętrzny stan
return state
def __setstate__(self, state):
self.__dict__.update(state)
self.internal_state = "restored internal" # Przywracamy wewnętrzny stan
def __repr__(self):
return f"CustomClass(value={self.value}, internal_state={self.internal_state})"
# Tworzenie obiektu
obj = CustomClass(42)
print("Oryginalny obiekt:", obj)
# Serializacja obiektu
serialized_obj = pickle.dumps(obj)
print("Zserializowany obiekt:", serialized_obj)
# Deserializacja obiektu
deserialized_obj = pickle.loads(serialized_obj)
print("Deserializowany obiekt:", deserialized_obj)
Przy deserializacji, w funkcji __setstate__()
, robimy dwie rzeczy:
- Aktualizujemy bieżący stan obiektu za pomocą metody
update()
. - Pole
internal_state
(i inne nieserializowalne pola) otrzymują nowe wartości.
GO TO FULL VERSION