Search code examples
pythonpython-dataclasses

How can I invert `dataclass.astuple`?


I am trying to construct a hierarchy of dataclasses from a tuple, like so:

from dataclasses import astuple, dataclass

@dataclass
class Child:
    name: str

@dataclass
class Parent:
    child: Child

# this is what I want
p = Parent(Child("Tim"))
print(p)

# this is what I get
t = astuple(p)
print(Parent(*t))

However, while this constructs a Parent as expected, its child is not of type Child:

Parent(child=Child(name='Tim'))
Parent(child=('Tim',))

Is there a way to construct Parent and child from the tuple t, or by some other means?


Solution

  • You can use a helper function that constructs an instance of a dataclass from a given tuple of values and recursively constructs child instances for fields that are dataclasses:

    from dataclasses import astuple, dataclass, fields, is_dataclass
    
    @dataclass
    class Child:
        name: str
    
    @dataclass
    class Parent:
        child: Child
    
    def from_tuple(cls, data):
        return cls(*(
            from_tuple(type, obj) if is_dataclass(type := field.type) else obj
            for obj, field in zip(data, fields(cls))
        ))
    
    p = Parent(Child("Tim"))
    t = astuple(p)
    print(from_tuple(Parent, t))
    

    This outputs:

    Parent(child=Child(name='Tim'))
    

    Demo here