Search code examples
pythonpython-3.xpydanticpython-dataclasses

Python: Use nested dict to create class of nested dataclass


In the basic case, one can easily map a dictionary to the parameters. The below shows the basic example.

def func1(x: int, y: int):
    return x+y

input = {
    "x": 1,
    "y": 2,
}

## This Works
sum = func1(**input)
# sum = 3

Does Python provide any other types of shortcuts which would enable this type of behavior for nested classes?

from dataclasses import dataclass

@dataclass
class X:
  x: int


@dataclass
class Y:
  y: int


def func2(x: X, y: Y):
    return x.x + y.y


input_2 = {
    "X": {
        "x": 1,
    },
    "Y": {
        "y": 1,
    },
}

sum = func2(**input_2)
# TypeError: func2() got an unexpected keyword argument 'X'

I have tried other approach's. This is an example fo something that works, but is not very general.

sum = func2(X(input_2[X][x]),Y(input_2[Y][y])

Also failed with pydantic

from pydantic import BaseModel

class X(BaseModel):
  x: int


class Y(BaseModel):
  y: int


def func2(x: X, y: Y):
    return x.x + y.y


input_2 = {
    "X": {
        "x": 1,
    },
    "Y": {
        "y": 1,
    },
}
sum = func2(**input_2)

Solution

  • @dataclass
    class Math:
    """Collection of Configurations and Data Loading Utilities for PlayFab Churn Featurization"""
        x: X
        y: Y
    
        @classmethod
        def load(cls, config_json):
            return Math(
                x=X(**config_json['x']),
                y=Y(**config_json['y']),
            )
    

    I want around the constructor and gave myself a different way out. I still get the benefits all of my nested dataclasses, maintain backwards compatibility with my old constructor, and still do not need a init method.