Home > front end >  Python: Use nested dict to create class of nested dataclass
Python: Use nested dict to create class of nested dataclass

Time:03-08

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)

CodePudding user response:

@dataclass
class ChurnFeaturization:
"""Collection of Configurations and Data Loading Utilities for PlayFab Churn Featurization"""
    storage: StorageConfig
    data: ChurnInputDataConfig
    labels: ChurnLabelConfig
    window: ChurnWindowConfig
    titles: ChurnTitleConfig

@classmethod
def load(cls, config_json):
    return ChurnFeaturization(
        storage=StorageConfig(**config_json['storage']),
        data=ChurnInputDataConfig(**config_json['data']),
        labels=ChurnLabelConfig(**config_json['label']),
        window=ChurnWindowConfig(**config_json['window']),
        titles=ChurnTitleConfig(**config_json['title']),
    )

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.

CodePudding user response:

I think create a new class that includes X and Y, assume C can work for your case

from pydantic import BaseModel

class X(BaseModel):
  x: int


class Y(BaseModel):
  y: int


class C(X, Y):
    pass

def func2(c: C):
    x = c.x
    y = c.y
    return x   y


input_2 = C(**{
    "x": 1,
    "y": 1,
})
sum = func2(input_2)
print(sum)
  • Related