Распаковать kwargs внутри класса данных

Я могу без проблем использовать kwargs при создании объекта класса данных:

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

Однако я хотел бы распаковать kwargs внутри класса данных, когда они не являются частью вызывающих аргументов:

@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')

person misantroop    schedule 10.10.2020    source источник
comment
Какая вам разница, будет ли распаковка производиться внутри класса или снаружи?   -  person DeepSpace    schedule 10.10.2020
comment
Как вы предлагаете подавать dic на ваш __post_init__, который вызывается __init__?   -  person Patrick Artner    schedule 10.10.2020
comment
@DeepSpace Потому что класс будет вызываться большое количество раз, и он указан на языке сценариев, введенном пользователем.   -  person misantroop    schedule 10.10.2020
comment
@PatrickArtner в постановке будет вызываться из другого класса.   -  person misantroop    schedule 10.10.2020
comment
не должны ли вы затем объявлять их dataclass.InitVar, как описано здесь: docs. python.org/3/library/dataclasses.html#init-only-variables ?   -  person Patrick Artner    schedule 10.10.2020


Ответы (2)


dataclass может явно определять метод __init__().

В документации указано:

Параметры dataclass():

init: если true (по умолчанию), будет создан метод __init__().

Если класс уже определяет __init__(), этот параметр игнорируется.

Следовательно, вы можете определить стандартный метод __init__() для обработки 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)
person Christopher Peisert    schedule 10.10.2020

Я получил немного другое решение, которое достигает намеченной цели:

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)
person misantroop    schedule 10.10.2020