Dict의 Python 데이터 클래스

Salman Mehmood 2023년6월21일
  1. 사전을 다시 데이터 클래스로 변환
  2. __post_init__를 사용하여 사전을 다시 데이터 클래스로 변환
  3. 사용자 지정 구현을 통해 사전을 다시 데이터 클래스로 변환
  4. dacite(타사 라이브러리)를 사용하여 사전을 다시 데이터 클래스로 변환
Dict의 Python 데이터 클래스

이 문서의 주요 목표는 중첩된 사전을 데이터 클래스로 변환하는 방법을 보여 주는 것입니다. 세 가지 유형의 접근법이 설명과 함께 제시됩니다.

사전을 다시 데이터 클래스로 변환

작업 중인 프로젝트에 따라 사전을 다시 데이터 클래스로 변환해야 하는 시나리오가 발생할 수 있습니다. 드문 경우일 수 있지만 특히 예기치 않은 동작을 방지하려는 경우 변환을 수행해야 할 수 있는 특정 상황이 있습니다.

이러한 시나리오의 예는 변환된 사전이 복잡한 유형의 멤버나 데이터 클래스인 멤버를 포함하는 것과 같이 중첩되거나 복잡하다는 것입니다.

from dataclasses import dataclass, asdict


@dataclass
class A:
    x: int


@dataclass
class B:
    x: A
    y: A


@dataclass
class C:
    a: B
    b: B

위의 경우 데이터 클래스 C는 사전으로 변환할 때 때때로 변환 문제를 일으킬 수 있습니다. 문제는 주로 클래스 구성원 유형을 처리하지 못하기 때문에 발생합니다.

이 솔루션을 극복하기 위해 선호도와 프로젝트의 특성에 따라 여러 접근 방식을 선택할 수 있습니다. 데이터 특성의 범위에 대해 잘 알고 있는 개인 프로젝트를 진행 중인 경우 간단한 해결 방법을 사용하는 것이 안전합니다.

그러나 대규모 데이터의 경우 일반적으로 안전하고 다양한 사용 사례에서 작동하도록 설계된 타사 라이브러리(가급적 오픈 소스)를 사용하는 것이 좋습니다. 따라서 더 넓은 범위의 데이터 변형을 처리할 수 있습니다.

__post_init__를 사용하여 사전을 다시 데이터 클래스로 변환

가장 쉬운 방법 중 하나는 데이터 클래스를 초기화한 후 자동으로 호출되는 __post_init__ 함수를 활용하는 것입니다.

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)

출력:

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

__post_init_ 함수는 ComplexDClazz 데이터 클래스가 초기화되면 호출됩니다. 이 고유한 속성으로 인해 사전을 다시 데이터 클래스로 변환하는 데 사용할 수 있습니다.

필요한 모든 구현은 __post_init_ 함수 내에서 수행됩니다. 코드는 두 가지 주요 부분으로 나눌 수 있습니다.

  1. 함수 시작 시 전달된 사전 dict가 멤버 simpKlazz의 유형과 동일한 유형인지 여부가 결정됩니다.
  2. 조건이 참이면 사전 값을 올바른 유형으로 변환한 후 멤버 변수 simpKlazz가 업데이트됩니다.

사용 적합성

작고 독립적이지만 솔루션은 다양한 유형의 데이터 클래스로 엄격한 테스트를 거친 후에도 잘 유지됩니다. 독립적이고 작은 솔루션을 찾고 있다면 이 솔루션이 좋은 선택처럼 보이지만 사용하려는 모든 데이터 클래스에 이 기능을 구현해야 할 수도 있습니다.

대규모 프로젝트에서 작업하는 경우 자체 테스트 사례를 솔루션에 적용하여 사용 사례에 얼마나 적합한지 확인하십시오.

사용자 지정 구현을 통해 사전을 다시 데이터 클래스로 변환

중첩된 사전을 다시 데이터 클래스로 변환하기 위한 다음 함수를 고려하십시오.

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

출력:

Success

이 간단한 5줄 코드는 두 가지 작업이 수행되는 try-catch 블록으로 구성됩니다.

  1. klass가 데이터 클래스라고 가정합니다. 데이터 클래스의 모든 필드가 추출되며 이름과 유형이 더 구체적입니다.
  2. 모든 필드가 검색된 후 klass 유형의 데이터 클래스 개체가 검색된 필드에서 생성됩니다. 재귀 호출은 필드 내부의 모든 중첩 클래스가 적절하게 처리되고 변환되도록 합니다.
  3. try 블록이 실패하면(주로 전달된 매개변수가 필수 유형이 아닌 경우) 원래 전달된 객체가 반환됩니다. 이렇게 하면 전달된 개체가 적합한 유형이 아닌 경우 반환되어 재귀 호출에 대한 중지 조건으로 작동합니다.

사용 적합성

이 방법은 매우 다양한 유형의 범위가 크지 않고 대부분의 사례가 알려진 소규모 프로젝트에 가장 적합합니다. 더 큰 규모의 프로젝트의 경우 이 방법은 코너 케이스를 만났을 때 예기치 않게 작동할 수 있습니다.

잠재적 오류를 근절하기 위해 데이터 클래스 형식의 테스트 사례로 이를 테스트하는 것이 좋습니다.

dacite(타사 라이브러리)를 사용하여 사전을 다시 데이터 클래스로 변환

‘dacite’는 Python에서 데이터 클래스 생성을 단순화하는 것을 목표로 하는 오픈 소스 타사 라이브러리입니다. 운 좋게도 라이브러리는 우리가 원하는 것을 수행하는 함수로 구성되어 있으며 전달된 사전(중첩 여부에 관계없이)에서 데이터 클래스를 생성합니다.

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

출력:

Success

‘dacite’는 주어진 사전 개체에서 데이터 클래스를 생성할 수 있는 ‘from_dict’라는 하나의 함수로만 구성됩니다.

기능을 사용하는 것은 매우 간단합니다. 데이터 클래스와 사전이라는 두 개의 매개변수로 구성됩니다.

그런 다음 이 함수는 주어진 사전을 주어진 유형의 데이터 클래스 개체로 변환하고 반환합니다. 이 모든 것이 사용자 지정 함수의 번거로움 없이 이루어집니다.

사용 적합성

오픈 소스의 좋은 점은 오류가 발생하는 경우 즉시 보고되고 수정 작업이 순간적으로 시작된다는 것입니다. 이 접근 방식은 만능이며 소규모 프로젝트와 대규모 프로젝트 모두에 사용할 수 있습니다.

이러한 사례가 발견되면 개발자 또는 다른 커뮤니티 구성원이 수정 사항 생성을 도울 수 있는 GitHub 리포지토리에 보고할 수 있습니다. 그러나 추가 타사 라이브러리를 다운로드하지 않으려는 경우 이 옵션이 가장 적합하지 않을 수 있습니다.

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

관련 문장 - Python Dictionary

관련 문장 - Python Dataclass