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__() потрібно:

  1. Скопіювати поточний стан об'єкта (задане службовим полем __dict__) в окрему змінну — словник state.
  2. Видалити з нього всі поля, які не потрібно серіалізувати.
  3. Повернути отриманий об'єкт як результат функції __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__(), ми робимо дві речі:

  1. Оновлюємо поточний стан об'єкта за допомогою методу update().
  2. Поле internal_state (і інші несеріалізовані поля) отримують нові значення.
undefined
1
Опрос
Робота з директоріями,  12 уровень,  9 лекция
недоступен
Робота з директоріями
Робота з директоріями