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
(и другие несериализуемые поля) получают новые значения.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ