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?
CodePudding user response:
The documentation mentions the following:
The
dataclass()
decorator examines the class to findfield
s. Afield
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.
CodePudding user response:
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?