10.1 ¡Será a mi manera!
A veces tus objetos almacenan muchas referencias a diferentes objetos de servicio que no quieres enviar por la red, o que no es posible enviar por la red: referencias a archivos, bases de datos, etc.
Para que la serialización funcione también en estos casos, se ideó dar a la clase la capacidad de gestionar su propia serialización. Para esto se utilizan métodos especiales: __reduce__(), __getstate__(), __setstate__(). Estos métodos permiten especificar cómo los objetos deben ser serializados y restaurados.
Métodos principales de serialización controlada:
-
__reduce__(): Indica cómo debe ser serializado un objeto. -
__getstate__(): Devuelve el estado del objeto para la serialización. -
__setstate__(self, state): Restaura el objeto desde el estado.
A continuación, te contaré más sobre ellos y cómo usarlos juntos.
10.2 Método __reduce__()
El método __reduce__() devuelve una tupla, que indica cómo debe ser serializado y deserializado un objeto. La tupla usualmente contiene:
- Una referencia a una función o clase que se usará para restaurar el objeto.
- Una tupla de argumentos para esta función o clase.
- Estado adicional del objeto (si es necesario).
Ejemplo:
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})"
# Creación del objeto
obj = CustomClass(42)
# Serialización del objeto
serialized_obj = pickle.dumps(obj)
print("Objeto serializado:", serialized_obj)
# Deserialización del objeto
deserialized_obj = pickle.loads(serialized_obj)
print("Objeto deserializado:", deserialized_obj)
Por defecto, la función __reduce__() tiene este comportamiento:
class CustomClass:
def __init__(self, value):
self.value = value
def __reduce__(self):
# Definición de la clase
cls = self.__class__
# Argumentos del constructor
args = (self.value,)
# Estado del objeto
state = self.__dict__
return (cls, args, state)
Devuelve una tupla que consta de tres objetos:
Referencia a la clase actualArgumentos del constructor (tupla)Referencia al estado actual del objeto
Si te satisface este comportamiento, no necesitas redefinir __reduce__().
10.3 Lectura y escritura de estado
Métodos __getstate__() y __setstate__()
Estos métodos se utilizan para gestionar el estado del objeto durante la serialización y deserialización.
-
__getstate__(): Devuelve el estado del objeto, que debe ser serializado. -
__setstate__(self, state): Restaura el objeto desde el estado.
Ejemplo:
Supongamos que queremos guardar no todos los campos del objeto, sino excluir algunos de ellos. Para esto, en el método __getstate__() necesitamos:
- Copiar el estado actual del objeto (dado por el campo de servicio
__dict__) en una variable separada: el diccionariostate. - Eliminar de él todos los campos que no necesitamos serializar.
- Devolver el objeto obtenido como resultado de la función
__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'] # Excluimos el estado interno
return state
def __setstate__(self, state):
self.__dict__.update(state)
self.internal_state = "restored internal" # Restauramos el estado interno
def __repr__(self):
return f"CustomClass(value={self.value}, internal_state={self.internal_state})"
# Creación del objeto
obj = CustomClass(42)
print("Objeto original:", obj)
# Serialización del objeto
serialized_obj = pickle.dumps(obj)
print("Objeto serializado:", serialized_obj)
# Deserialización del objeto
deserialized_obj = pickle.loads(serialized_obj)
print("Objeto deserializado:", deserialized_obj)
Durante la deserialización, en la función __setstate__(), hacemos dos cosas:
- Actualizamos el estado actual del objeto usando el método
update(). - El campo
internal_state(y otros campos no serializables) reciben nuevos valores.
GO TO FULL VERSION