Unpack kwargs inside dataclass

4.5k views Asked by At

I can use kwargs when creating a dataclass object without issues:

@dataclass()
class Data:
    name: str =         'Unnamed'
    additional: int =   None
    things: int =       None

dic = {'additional': 123, 'things': 456}
res = Data(name='Somename', **dic)

Output: Data(name='Somename', additional=123, things=456)

However, I'd like to unpack the kwargs inside the data class when they're not part of calling arguments:

@dataclass()
class Data:
    name: str =         'Unnamed'
    additional: int =   None
    things: int =       None

    def __post_init__(self):
        self(**dic) #unpack kwargs to fields

dic = {'additional': 123, 'things': 456}
res = Data(name='Somename')
2

There are 2 answers

0
Christopher Peisert On

A dataclass may explicitly define an __init__() method.

The documentation states:

The parameters to dataclass() are:

init: If true (the default), a __init__() method will be generated.

If the class already defines __init__(), this parameter is ignored.

Hence, you may define a standard __init__() method to process kwargs.

@dataclass()
class Data:
    name: str
    additional: int
    things: int

    def __init__(self, name: str = 'Unnamed', additional: int = None, things: int = None, **kwargs):
        for key, value in kwargs.items():
            setattr(self, key, value)
0
misantroop On

I ended up with a slightly different solution which achieves the intended goal:

dic = {'Somename': 123}

@dataclass()
class Data:
    name: str =         'Unnamed'
    additional: int =   None
    things: int =       None
    arg: int =          None

    def __post_init__(self):
        self.arg = dic.get(self.name, None)

res = Data(name='Somename')

Data(name='Somename', additional=None, things=None, arg=123)