Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I provide defaults for a subclass of a dataclass?

I want to create a class hierarchy, where all objects of class Base has a field field1, but different subclasses have different default values for field1. The classes are data holders, so dataclasses seems like the perfect library to use.

Consider the following python 3.7+ code.

from dataclasses import dataclass, field
from typing import Any, Iterable

@dataclass
class Base:
    field1: Iterable[Any]

@dataclass
class Sub(Base):
    field2: Any
    field1: Iterable[Any] = field(default_factory=list)

The code fails, giving me TypeError: non-default argument 'field2' follows default argument. This is a little surprising, since field2 follows the non-default field1 of the superclass, and the defalt argument field1 of the class Sub actually comes after field2.

According to the example in the docs on dataclass inheritence though, fields in subclasses overrides the fields in superclasses, but field order is preserved. So the error makes sense.

Is there any suitable workaround here, or must I implement everything by hand?

like image 215
LudvigH Avatar asked Nov 06 '22 05:11

LudvigH


People also ask

Can a Dataclass inherit from another class?

Inheriting a data class from another data class is not allowed because there is no way to make compiler-generated data class methods work consistently and intuitively in case of inheritance. yole: You can inherit a data class from a non-data class.

Can a Dataclass have methods?

dataclasses has a special method called __post_init__ . As the name clearly suggests, this method is called right after the __init__ method is called. Going back to the previous example, we can see how this method can be called to initialize an internal attribute that depends on previously set attributes.

How do you initialize a Dataclass in Python?

Defining a data class. A Python class is a program used to create objects and their properties. We use the keyword class to create a class in Python. For class attributes to be initialized, we use a constructor method called __init__() which is called when an object is created in a Python class.

Can DataClasses inherit Python?

When you use Python inheritance to create dataclasses, you cannot guarantee that all fields with default values will appear after all fields without default values. An easy solution is to avoid using multiple inheritance to construct a "merged" dataclass.


1 Answers

You can use the @property decorator:

from dataclasses import dataclass
from typing import Any, Iterable

@dataclass
class Base:
    @property
    def field1(self) -> Iterable[Any]:
        return

@dataclass
class Sub(Base):
    field2: Any

    @property
    def field1(self) -> Iterable[Any]:
        return []  # or whatever default you want to put here
like image 58
Ben Caine Avatar answered Nov 14 '22 21:11

Ben Caine