0

I ran into this bizzare behaviour of dataclasses when intermixed with inheritance/type annotations:

>>> @dataclass
... class Base:
...     a: int = 10
...
>>>
>>> @dataclass
... class Derived(Base):
...     a = 20
...
>>>
>>> Derived.a
20
>>> Derived().a
10

Note that if I add annotation on a in Derived, then things behave reasonably.

What exactly is going on here?

khelwood
  • 55,782
  • 14
  • 81
  • 108
skgbanga
  • 2,477
  • 2
  • 20
  • 29

2 Answers2

4

The documentation mentions the following:

The dataclass() decorator examines the class to find fields. A field is defined as a class variable that has a type annotation. [...]

Hence, in the definition of Derived, a = 20 is not identified as a field and thus it is not added to the __init__ method of the class. When creating an instance of that class, it will use the original parameter definition from Base which has 10 as a default value.

a_guest
  • 34,165
  • 12
  • 64
  • 118
1

a: int in a dataclass declares an instance attribute, because that is how dataclasses are designed to work. (See dataclasses documentation.)

a = 20 in Derived defines a class attribute, because that is how class attributes are defined. So the class Derived has an attribute a with the value 20, but an instance of Derived has (inherited from Base) an instance attribute with the default value 10.

See also How to add a dataclass field without annotating the type?

khelwood
  • 55,782
  • 14
  • 81
  • 108