How to create an optional field in a dataclass that is inherited? How to create an optional field in a dataclass that is inherited? python-3.x python-3.x

How to create an optional field in a dataclass that is inherited?


The underlying problem that you have seems to be the same one that is described here. The short version of that post is that in a function signature (including the dataclass-generated __init__ method), obligatory arguments (like NamedEvent's name) can not follow after arguments with default values (which are necessary to define the behavior of Event's updated_at) - a child's fields will always follow after those of its parent.

So either you have no default values in your parent class (which doesn't work in this case) or all your child's fields need default values (which is annoying, and sometimes simply not feasible).

The post I linked above discusses some patterns that you can apply to solve your problem, but as a nicer alternative you can also use the third part party package pydantic which already solved this problem for you. A sample implementation could look like this:

import pydanticfrom datetime import datetimeclass Event(pydantic.BaseModel):    id: str    created_at: datetime = None    updated_at: datetime = None    @pydantic.validator('created_at', pre=True, always=True)    def default_created(cls, v):        return v or datetime.now()    @pydantic.validator('updated_at', pre=True, always=True)    def default_modified(cls, v, values):        return v or values['created_at']class NamedEvent(Event):    name: str

The default-value specification through validators is a bit cumbersome, but overall it's a very useful package that fixes lots of the shortcomings that you run into when using dataclasses, plus some more.

Using the class definition, an instance of NamedEvent can be created like this:

>>> NamedEvent(id='1', name='foo')NamedEvent(id='1', created_at=datetime.datetime(2020, 5, 2, 18, 50, 12, 902732), updated_at=datetime.datetime(2020, 5, 2, 18, 50, 12, 902732), name='foo')