I tried this code:
from dataclasses import dataclass
@dataclass
class Data1:
d11: str
d12: float
@dataclass
class Data2:
d21: str
d22: float
@dataclass
class D3(Data1, Data2): pass
print(D3.__annotations__)
But the annotations for D3
are only {'d11': <class 'str'>, 'd12': <class 'float'>}
. Why does it not include annotations for the Data2
fields?
__annotations__
is for the literal annotations in the class
body. It is not intended to represent inheritance at all.
If, for example, D3
actually has annotations only these are visible:
@dataclass
class D3(Data1, Data2):
a: 3
print(D3.__annotations__) # {'a': 3}
Note that the "inherited annotations" are available via typing.get_type_hints
, which achieves this by "merging all the __annotations__
along C.__mro__
in reverse order". For dataclasses, dataclasses.fields
also provides the full Field
specifications for a class or instance.
In your specific case, the __annotations__
are non-empty due to a bug fixed in Python 3.10. Prior to Python 3.10, __annotations__
is only created when there actually are annotations; this means that if a parent class has annotations but a child class does not, the parent annotations are visible via the usual attribute lookup.
Accessing the actual class
' annotation, i.e. circumventing parent attribute lookup
@dataclass
class D3(Data1, Data2):
pass
print(D3.__dict__["__annotations__"])
will trigger KeyError: '__annotations__'
in Python 3.9 or earlier, and print {}
in Python 3.10 or later.