In Python, I have a dataclass that holds over a dozen members. I use it to create a dict that I post into ElasticSearch.
Now I want to get a dict from ElasticSearch and use it to initialize the dataclass.
Since:
- Python doesn't allow to create a second __ init __ with a different signature.
- I don't want to manually write the __ init __ which is auto-generated just to add an optional parameter
- I don't want to add an optional parameter to accept the dict, just so that the __ init __ remains auto-generated.
I thought of adding a 2nd method init2, which will return an instance of the dataclass and parse the passed dict parameter into the auto-generated __ init __ method.
I would appriciate your input to decide if my suggested solution below is the correct implementation.
Also, Can this implementation be considered as a type of factory?
Thanks.
Follow up: Since the JSON\dictionary I get from the ES request is:
Has exactly the same keywords as the dataclass
Is flat, i.d., there are no nested objects.
I could simply pass the values as a **dict into the the auto-generated __ init __ method.
See my answer below for this specific case:
from dataclasses import dataclass
@dataclass
class MyData:
name: str
age: int = 17
@classmethod
def init_from_dict(cls, values_in_dict: dict):
# Original line using MyData was fixed to use cls, following @ForceBru 's comment
# return MyData(values_in_dict['name'], age=values_in_dict['age'])
return cls(values_in_dict['name'], age=values_in_dict['age'])
my_data_1: MyData = MyData('Alice')
print(my_data_1)
my_data_2: MyData = MyData('Bob', 15)
print(my_data_2)
values_in_dict_3: dict = {
'name': 'Carol',
'age': 20
}
my_data_3: MyData = MyData.init_from_dict(values_in_dict_3)
print(my_data_3)
# Another init which uses the auto-generated __init__ works in this specific
# case because the values' dict is flat and the keywords are the same as the
# parameter names in the dataclass.
# This allows me to do this
my_data_4: MyData = MyData(**values_in_dict_3)