Python-Datenklasse aus Dict

Salman Mehmood 21 Juni 2023
  1. Konvertieren Sie ein Wörterbuch zurück in eine Datenklasse
  2. Konvertieren Sie ein Wörterbuch zurück in eine Datenklasse mit __post_init__
  3. Konvertieren Sie ein Wörterbuch zurück in eine Datenklasse mit benutzerdefinierter Implementierung
  4. Konvertieren Sie ein Wörterbuch zurück in eine Datenklasse mit dacite (Third Party Library)
Python-Datenklasse aus Dict

Das Hauptziel dieses Artikels besteht darin, zu demonstrieren, wie ein verschachteltes Wörterbuch in eine Datenklasse konvertiert wird. Drei verschiedene Arten von Ansätzen werden zusammen mit ihren Erläuterungen vorgestellt.

Konvertieren Sie ein Wörterbuch zurück in eine Datenklasse

Abhängig von dem Projekt, an dem Sie arbeiten, kann es vorkommen, dass Sie ein Wörterbuch wieder in eine Datenklasse konvertieren müssen. Obwohl dies ein seltener Fall sein mag, gibt es bestimmte Situationen, in denen Sie die Konvertierung möglicherweise durchführen müssen, insbesondere wenn Sie unerwartetes Verhalten verhindern möchten.

Ein Beispiel für ein solches Szenario wäre, dass das konvertierte Wörterbuch verschachtelt oder komplex ist, z. B. Mitglieder mit komplexen Typen oder Mitglieder, die Datenklassen sind.

from dataclasses import dataclass, asdict


@dataclass
class A:
    x: int


@dataclass
class B:
    x: A
    y: A


@dataclass
class C:
    a: B
    b: B

Im obigen Fall kann die Datenklasse C bei der Konvertierung in ein Wörterbuch manchmal zu Konvertierungsproblemen führen. Die Probleme treten hauptsächlich aufgrund einer fehlgeschlagenen Behandlung von Typen von Klassenmitgliedern auf.

Um diese Lösung zu überwinden, können Sie je nach Ihren Vorlieben und der Art des Projekts mehrere Ansätze wählen. Wenn Sie an einem persönlichen Projekt arbeiten und eine gute Vorstellung vom Umfang der Art der Daten haben, ist es sicher, einfache Problemumgehungen zu verwenden.

Bei großen Datenmengen wird jedoch im Allgemeinen empfohlen, sicher zu sein und Bibliotheken von Drittanbietern (vorzugsweise Open Source) zu verwenden, da diese für den Betrieb in einem großen Spektrum von Anwendungsfällen ausgelegt sind. Dadurch können sie mit einer größeren Bandbreite an Datenvarianten umgehen.

Konvertieren Sie ein Wörterbuch zurück in eine Datenklasse mit __post_init__

Einer der einfachsten Ansätze besteht darin, die Funktion __post_init__ zu nutzen, die automatisch nach der Initialisierung der Datenklasse aufgerufen wird.

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)

Ausgang:

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

Die Funktion __post_init_ wird aufgerufen, sobald die Datenklasse ComplexDClazz initialisiert ist. Aufgrund dieser einzigartigen Eigenschaft können wir dies verwenden, um das Wörterbuch zurück in eine Datenklasse zu konvertieren.

Alle notwendigen Implementierungen werden innerhalb der Funktion __post_init_ durchgeführt. Der Code lässt sich in zwei Hauptteile unterteilen:

  1. Beim Start der Funktion wird festgestellt, ob das übergebene Dictionary dict den gleichen Typ hat wie unser Member simpKlazz.
  2. Wenn die Bedingung wahr ist, wird die Elementvariable simpKlazz aktualisiert, nachdem die Wörterbuchwerte in den richtigen Typ konvertiert wurden.

Eignung für den Einsatz

Obwohl klein und unabhängig, hält die Lösung auch nach strengen Tests mit verschiedenen Arten von Datenklassen. Wenn Sie nach einer unabhängigen und kleinen Lösung suchen, scheint diese Lösung eine gute Wahl zu sein, aber Sie müssen diese Funktion möglicherweise in jeder Datenklasse implementieren, die Sie verwenden möchten.

Wenn Sie an einem Großprojekt arbeiten, wenden Sie Ihre eigenen Testfälle auf die Lösung an, um zu sehen, wie sie für Ihre Anwendungsfälle geeignet ist.

Konvertieren Sie ein Wörterbuch zurück in eine Datenklasse mit benutzerdefinierter Implementierung

Betrachten Sie die folgende Funktion zum Konvertieren eines verschachtelten Wörterbuchs zurück in die Datenklasse.

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")

Ausgang:

Success

Dieser einfache Fünf-Zeilen-Code besteht aus einem try-catch-Block, in dem zwei Dinge erledigt werden:

  1. Angenommen, klasse ist eine Datenklasse. Alle Felder in der Datenklasse werden extrahiert, genauer gesagt ihre Namen und Typen.
  2. Nachdem alle Felder abgerufen wurden, wird aus den abgerufenen Feldern ein Datenklassenobjekt vom Typ klasse generiert. Der rekursive Aufruf stellt sicher, dass alle weiter innerhalb der Felder verschachtelten Klassen behandelt und entsprechend konvertiert werden.
  3. Wenn der try-Block fehlschlägt (meistens, wenn die übergebenen Parameter nicht die erforderlichen Typen sind), wird das ursprünglich übergebene Objekt zurückgegeben. Dadurch wird sichergestellt, dass, wenn das übergebene Objekt keinen geeigneten Typ hat, es zurückgegeben wird und als Stoppbedingung für den rekursiven Aufruf dient.

Eignung für den Einsatz

Diese Methode eignet sich am besten für kleinere Projekte, bei denen der Spielraum für sehr unterschiedliche Typen nicht groß ist und die meisten Fälle bekannt sind. Bei größeren Projekten kann diese Methode unerwartet funktionieren, wenn sie auf einen Grenzfall stößt.

Es wird empfohlen, dies mit Testfällen Ihrer Datenklassenformate zu testen, um mögliche Fehler auszumerzen.

Konvertieren Sie ein Wörterbuch zurück in eine Datenklasse mit dacite (Third Party Library)

dacite ist eine Open-Source-Bibliothek eines Drittanbieters, die darauf abzielt, die Erstellung von Datenklassen in Python zu vereinfachen. Glücklicherweise besteht die Bibliothek aus der Funktion, die das tut, was wir wollen, eine Datenklasse aus einem übergebenen Wörterbuch erstellen (verschachtelt oder nicht).

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")

Ausgang:

Success

dacite besteht aus nur einer Funktion, from_dict, die die Erstellung einer Datenklasse aus einem gegebenen Dictionary-Objekt erlaubt.

Die Verwendung der Funktion ist ziemlich einfach. Es besteht aus zwei Parametern: einer Datenklasse und einem Wörterbuch.

Die Funktion konvertiert dann das angegebene Wörterbuch in das Datenklassenobjekt des angegebenen Typs und gibt dieses zurück – alles ohne den Aufwand benutzerdefinierter Funktionen.

Eignung für den Einsatz

Das Gute an Open Source ist, dass auftretende Fehler sofort gemeldet werden und sofort mit der Arbeit an Fehlerbehebungen begonnen wird. In Anbetracht dessen ist dieser Ansatz vielseitig und kann sowohl für kleine als auch für große Projekte funktionieren.

Wenn solche Fälle gefunden werden, können sie an das GitHub-Repository gemeldet werden, wo der Entwickler oder andere Community-Mitglieder helfen können, einen Fix zu generieren. Diese Option scheint jedoch nicht die praktikabelste zu sein, wenn Sie keine zusätzliche Bibliothek von Drittanbietern herunterladen möchten.

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

Verwandter Artikel - Python Dictionary

Verwandter Artikel - Python Dataclass