Clase de datos de Python de Dict

Salman Mehmood 21 junio 2023
  1. Convertir un diccionario nuevamente en una clase de datos
  2. Convierta un diccionario nuevamente en una clase de datos con __post_init__
  3. Convierta un diccionario nuevamente en una clase de datos con implementación personalizada
  4. Convierta un diccionario nuevamente en una clase de datos con dacite (Biblioteca de terceros)
Clase de datos de Python de Dict

El objetivo principal de este artículo es demostrar cómo convertir un diccionario anidado en una clase de datos. Se presentan tres tipos diferentes de enfoques, junto con sus explicaciones.

Convertir un diccionario nuevamente en una clase de datos

Según el proyecto en el que esté trabajando, es posible que se encuentre con un escenario en el que necesite volver a convertir un diccionario en una clase de datos. Si bien puede ser un caso raro, hay ciertas situaciones en las que es posible que deba realizar la conversión, especialmente cuando desea evitar un comportamiento inesperado.

Un ejemplo de tal escenario sería que el diccionario convertido esté anidado o sea complejo, como tener miembros con tipos complejos o miembros que sean clases de datos.

from dataclasses import dataclass, asdict


@dataclass
class A:
    x: int


@dataclass
class B:
    x: A
    y: A


@dataclass
class C:
    a: B
    b: B

En el caso anterior, la clase de datos C a veces puede presentar problemas de conversión cuando se convierte en un diccionario. Los problemas ocurren principalmente debido al manejo fallido de tipos de miembros de clase.

Para superar esta solución, puede elegir varios enfoques según sus preferencias y la naturaleza del proyecto. Si está trabajando en un proyecto personal con una buena idea del alcance de la naturaleza de los datos, es seguro utilizar soluciones simples.

Sin embargo, en el caso de datos escalables a gran escala, generalmente se recomienda estar seguro y usar bibliotecas de terceros (preferiblemente de código abierto), ya que están diseñadas para operar en un amplio espectro de casos de uso. Por lo tanto, les permite manejar una gama más amplia de variantes de datos.

Convierta un diccionario nuevamente en una clase de datos con __post_init__

Uno de los enfoques más sencillos es aprovechar la función __post_init__ que se llama automáticamente después de inicializar la clase de datos.

from dataclasses import dataclass, asdict


@dataclass
class SimpleDClazz:
    m_one: str
    m_two: str


@dataclass
class ComplexDClazz:
    simpKlazz: SimpleDClazz

    def __post_init__(self):
        if isinstance(self.simpKlazz, dict):
            self.simpKlazz = SimpleDClazz(**self.simpKlazz)


foo = ComplexDClazz(simpKlazz=SimpleDClazz(m_one="1", m_two="2"))

d = asdict(foo)
print(d)
o = ComplexDClazz(**d)
print(o)

Producción :

{'simpKlazz': {'m_one': '1', 'm_two': '2'}}
ComplexDClazz(simpKlazz=SimpleDClazz(m_one='1', m_two='2'))

La función __post_init_ se llama una vez que se inicializa la clase de datos ComplexDClazz. Debido a esta propiedad única, podemos usar esto para ayudar a convertir el diccionario nuevamente en una clase de datos.

Todas las implementaciones necesarias se realizan dentro de la función __post_init_. El código se puede dividir en dos partes principales:

  1. Al comienzo de la función, se determina si el diccionario dict pasado tiene el mismo tipo que el tipo de nuestro miembro, simpKlazz.
  2. Si la condición es verdadera, la variable miembro simpKlazz se actualiza después de convertir los valores del diccionario al tipo correcto.

Idoneidad para el uso

Aunque pequeña e independiente, la solución resiste incluso después de pruebas rigurosas con diferentes tipos de clases de datos. Si está buscando una solución independiente y pequeña, esta solución parece una buena opción, pero es posible que deba implementar esta función en cada clase de datos que planee usar.

Si está trabajando en un proyecto a gran escala, aplique sus propios casos de prueba a la solución para ver qué tan adecuada es para sus casos de uso.

Convierta un diccionario nuevamente en una clase de datos con implementación personalizada

Considere la siguiente función para volver a convertir un diccionario anidado en la clase de datos.

import dataclasses as dc
from dataclasses import dataclass, asdict


def dict_to_dataklass(klass, d):
    try:
        fieldtypes = {f.name: f.type for f in dc.fields(klass)}
        return klass(**{f: dict_to_dataklass(fieldtypes[f], d[f]) for f in d})
    except:
        return d  # The object is not a dataclass field


@dataclass
class SimpleDClazz:
    x: float
    y: float


@dataclass
class ComplexDClazz:
    a: SimpleDClazz
    b: SimpleDClazz


line = ComplexDClazz(SimpleDClazz(1, 2), SimpleDClazz(3, 4))
assert line == dict_to_dataklass(ComplexDClazz, asdict(line))
print("Success")

Producción :

Success

Este código simple de cinco líneas consta de un bloque try-catch, en el que se hacen dos cosas:

  1. Suponiendo que klass es una clase de datos. Se extraen todos los campos de la clase de datos, sus nombres y tipos para ser más específicos.
  2. Después de recuperar todos los campos, se genera un objeto de clase de datos de tipo klass a partir de los campos recuperados. La llamada recursiva garantiza que las clases anidadas más adentro de los campos se manejen y conviertan en consecuencia.
  3. Cuando el bloque try falla (generalmente cuando los parámetros pasados no son los tipos requeridos), se devuelve el objeto pasado original. Esto asegura que si el objeto pasado no es de un tipo adecuado, se devuelve, actuando como una condición de parada para la llamada recursiva.

Idoneidad para el uso

Este método es más adecuado para proyectos más pequeños donde el alcance para tipos muy diferentes no es grande y la mayoría de los casos son conocidos. En cuanto a proyectos de mayor escala, este método puede funcionar inesperadamente cuando se encuentra con un caso de esquina.

Se recomienda probar esto con casos de prueba de sus formatos de clase de datos para eliminar posibles errores.

Convierta un diccionario nuevamente en una clase de datos con dacite (Biblioteca de terceros)

dacite es una biblioteca de terceros de código abierto que tiene como objetivo simplificar la creación de clases de datos en Python. Afortunadamente, la biblioteca consta de la función que hace lo que queremos, crear una clase de datos a partir de un diccionario pasado (anidado o no).

from dataclasses import dataclass
from dacite import from_dict


@dataclass
class DKlazz:
    m_one: str
    m_two: int
    is_working: bool


sample = {
    "m_one": "1",
    "m_two": 2,
    "is_working": False,
}

dk = from_dict(data_class=DKlazz, data=sample)

assert dk == DKlazz(m_one="1", m_two=2, is_working=False)
print("Success")

Producción :

Success

dacite consta de una sola función, from_dict, que permite la creación de una clase de datos a partir de un objeto de diccionario dado.

El uso de la función es bastante sencillo. Consta de dos parámetros: una clase de datos y un diccionario.

Luego, la función convierte el diccionario dado en el objeto de clase de datos del tipo dado y lo devuelve, todo sin la molestia de las funciones personalizadas.

Idoneidad para el uso

Lo bueno del código abierto es que, en caso de que se encuentre algún error, se informa de inmediato y el trabajo de corrección comienza momentáneamente. Teniendo eso en cuenta, este enfoque es completo y puede funcionar tanto para proyectos de pequeña como de gran escala.

Si se encuentran tales casos, se pueden informar al repositorio de GitHub, donde el desarrollador u otros miembros de la comunidad pueden ayudar a generar una solución. Sin embargo, esta opción puede no parecer la más viable si no desea descargar ninguna biblioteca adicional de terceros.

Salman Mehmood avatar Salman Mehmood avatar

Hello! I am Salman Bin Mehmood(Baum), a software developer and I help organizations, address complex problems. My expertise lies within back-end, data science and machine learning. I am a lifelong learner, currently working on metaverse, and enrolled in a course building an AI application with python. I love solving problems and developing bug-free software for people. I write content related to python and hot Technologies.

LinkedIn

Artículo relacionado - Python Dictionary

Artículo relacionado - Python Dataclass