10.1 Все будет по-моему!
Иногда в ваших объектах хранится много ссылок на различные служебные объекты, которые вы не хотите передавать по сети, или которые невозможно передать по сети: ссылки на файлы, базы данных и т.п.
Чтобы сериализация работала и в таких случаях, придумали дать классу возможность самому управлять своей сериализацией. Для этого используются специальные методы: __reduce__(), __getstate__(), __setstate__(). Эти методы позволяют указать, как объекты должны быть сериализованы и восстановлены.
Основные методы управляемой сериализации:
-
__reduce__(): Указывает, как объект должен быть сериализован. -
__getstate__(): Возвращает состояние объекта для сериализации. -
__setstate__(self, state): Восстанавливает объект из состояния.
Ниже я расскажу о них подробнее, и как их вместе использовать.
10.2 Метод __reduce__()
Метод __reduce__() возвращает кортеж, который указывает, как объект должен быть сериализован и десериализован. Кортеж обычно содержит:
- Ссылку на функцию или класс, который будет использоваться для восстановления объекта.
- Кортеж аргументов для этой функции или класса.
- Дополнительное состояние объекта (если необходимо).
Пример:
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})"
# Создание объекта
obj = CustomClass(42)
# Сериализация объекта
serialized_obj = pickle.dumps(obj)
print("Сериализованный объект:", serialized_obj)
# Десериализация объекта
deserialized_obj = pickle.loads(serialized_obj)
print("Десериализованный объект:", deserialized_obj)
По умолчанию функция __reduce__() имеет такое поведение:
class CustomClass:
def __init__(self, value):
self.value = value
def __reduce__(self):
# Определение класса
cls = self.__class__
# Аргументы конструктора
args = (self.value,)
# Состояние объекта
state = self.__dict__
return (cls, args, state)
Она возвращает кортеж, состоящий из трёх объектов:
Ссылка на текущий классАргументы конструктора (кортеж)Ссылка на текущее состояние объекта
Если вас такое поведение устраивает — __reduce__() можете не переопределять.
10.3 Чтение и запись состояния
Методы __getstate__() и __setstate__()
Эти методы используются для управления состоянием объекта во время сериализации и десериализации.
-
__getstate__(): Возвращает состояние объекта, которое должно быть сериализовано. -
__setstate__(self, state): Восстанавливает объект из состояния.
Пример:
Допустим, мы хотим сохранить не все поля объекта, а исключить некоторые из них. Для этого в методе __getstate__() нужно:
- Скопировать текущее состояние объекта (заданное служебным полем
__dict__) в отдельную переменную — словарьstate. - Удалить из неё все поля, которые не нужно сериализовать.
- Вернуть полученный объект как результат функции
__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'] # Исключаем внутреннее состояние
return state
def __setstate__(self, state):
self.__dict__.update(state)
self.internal_state = "restored internal" # Восстанавливаем внутреннее состояние
def __repr__(self):
return f"CustomClass(value={self.value}, internal_state={self.internal_state})"
# Создание объекта
obj = CustomClass(42)
print("Оригинальный объект:", obj)
# Сериализация объекта
serialized_obj = pickle.dumps(obj)
print("Сериализованный объект:", serialized_obj)
# Десериализация объекта
deserialized_obj = pickle.loads(serialized_obj)
print("Десериализованный объект:", deserialized_obj)
При десериализации, в функции __setstate__(), мы делаем две вещи:
- Обновляем текущее состояние объекта с помощью метода
update(). - Поле
internal_state(и другие несериализуемые поля) получают новые значения.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ