Question: Given a dataclass structure: @dataclass class RichParent: many_fields: int = 1 more_fields: bool = False class Child(RichParent): some_extra: bool = False def __init__(seed: RichParent): # how to init more_fields and more_fields fields here without referencing them directly? # self.more_fields = seed.more_fields # self.many_fields = seed.many_fields pass  What would be the right way to shallow copy seed object fields into the new child object? I wouldn't mind even converting seed to Child type since there is no use for parent object after initialization. Why do I do that? I want to avoid changing Child class every time RichParent has a change as long as parent stays a plain dataclass.

Answer: I am unsure why you'd want to write an explicit __init__ *, although you may need to be on Python 3.10 to be able to pass in fields specific to Child to its init. ** from dataclasses import dataclass @dataclass(kw_only=True) class RichParent: many_fields: int = 1 more_fields: bool = False #for some reason not setting `@dataclass`` again here means the built in str/repr #skips the child-only field. #also if you don't use `kw_only=True` on Child, can't pass in Child only fields @dataclass(kw_only=True) class Child(RichParent): some_extra: bool = False seed = RichParent(many_fields=2, more_fields=True) print(f"\n{seed=}") child = Child(**vars(seed)) print(f"\n{child=} with {vars(child)=} which does include more_fields") child2 = Child(**vars(seed),some_extra=True) print(f"\n{child2=}") #see the behavior changes in print and field acceptable to constructor class ChildNoDC(RichParent): some_extra: bool = False child_no_dcdec = ChildNoDC(**vars(seed)) print(f"\n{child_no_dcdec=} with {vars(child_no_dcdec)=} which does include more_fields") try: child_no_dcdec2 = ChildNoDC(some_extra=True,**vars(seed)) except (Exception,) as e: print("\n",e, "as expected")  output: seed=RichParent(many_fields=2, more_fields=True) child=Child(many_fields=2, more_fields=True, some_extra=False) with vars(child)={'many_fields': 2, 'more_fields': True, 'some_extra': False} which does include more_fields child2=Child(many_fields=2, more_fields=True, some_extra=True) child_no_dcdec=ChildNoDC(many_fields=2, more_fields=True) with vars(child_no_dcdec)={'many_fields': 2, 'more_fields': True} which does include more_fields RichParent.__init__() got an unexpected keyword argument 'some_extra' as expected  * If you did need some custom init on Child, use the builtin post_init hook to do it:  def __post_init__(self): print(f"{self} lets do stuff here besides the std data init...")  From talking about shallow copies, you know about mutability issues, but you could hack some stuff like self.my_dict = self.my_dict.copy() hacks here to work around that. ** as far as I understand, @dataclass does not flip the class into a dataclass type. It just builds an __init__ and some methods, (using metaclasses?). So ChildNoDC doesn't know it is dataclass-style class and just tries to pass all fields passed into its constructor call onto Parent's __init__. Child having been "told" it's dataclassed too, knows better. (That's also the reason the child-only field wasn't being printed). And kw-only flag frees up some positioning and defaults-only constraints too.