0
votes

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)
2
It's not JSON, it's dictionaries :)dekuShrub
You get the TypeError because the keys of the dictionary must map to the names of the arguments of the function. Since you have a key "X", python expects an argument named X. Instead you have one named x with type X. I don't know of any way to map the elements of the dictionary to arguments based on the type annotation.Code-Apprentice
The problem with this is that it assumes every argument has a different type. That is usually a very bad assumption.user2357112 supports Monica

2 Answers

0
votes
@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.

0
votes

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)