Dataclasses.field Doesn't Resolve Type Annotation To Actual Type
Solution 1:
This is deliberate. Resolving type hints at import time is expensive, especially when from __future__ import annotations
has been used to disable resolving them in the first place.
Initially, the addition of the PEP 563 to Python 3.7 broke dataclasses when you used the from __future__ import annotations
switch and included ClassVar
or InitVar
type annotations for fields; these would not be resolved at this point and remained a string. This was already a problem before PEP 563 if you explicitly used strings, see dataclasses issue #92. This became a Python bug, #33453, once dataclasses made it into Python 3.7 proper.
The 'parent' project, attrs
, which inspired dataclasses
, also had this issue to solve. There, Łukasz Langa (co-author of most of the type hinting peps, including PEP 563), states:
OK, so I tried the above and it seems it's a nuclear option since it forces all annotations to be evaluated. This is what I wanted to avoid with
from __future__ import annotations
.
and in the discussion on the pull request that fixed issue 33453, Eric Smith, author of dataclasses
, stated:
I've been researching doing just that. I think @ambv's point is that it introduces a performance hit due to calling eval on every field, while the point of string annotations is to remove a performance hit.
Moreover, there were other problems; you can't evaluate all type hints at import time, not when they use forward references:
In addition to the performance issue, in the following case (without a
__future__
statement and without dataclasses), I get an error onget_type_hints()
becauseC
is undefined whenget_type_hints()
is called. This is python/typing#508. Notice that whereget_type_hints()
is called in this example is exactly where@dataclass
is going to run and would need to call the stripped downget_type_hints()
.
So in the end, all that dataclasses
does is do is apply string heuristics to the annotations, and will not load them for you.
To retrieve the type, just use get_type_hints()
on the class itself, and us the field .name
attribute as the key into the result:
resolved = typing.get_type_hints(C)
f = dataclasses.fields(C)[0]
ftype = resolved[f.name]
Post a Comment for "Dataclasses.field Doesn't Resolve Type Annotation To Actual Type"