Это умышленно.Разрешение подсказок типа во время импорта стоит дорого , особенно когда from __future__ import annotations
использовалось, чтобы отключить их разрешение в первую очередь.
Первоначально добавление PEP 563 в Python 3.7 прервалоськлассы данных, когда вы использовали переключатель from __future__ import annotations
и включали аннотации типа ClassVar
или InitVar
для полей;они не будут решены на этом этапе и останутся строкой.Это уже было проблемой до PEP 563, если вы явно использовали строки, см. выпуск классов данных # 92 .Эта ошибка стала Python, # 33453 , когда классы данных превратили ее в собственный Python 3.7.
Родительский проект, attrs
, который также вдохновил dataclasses
, пришлось решить эту проблему .Там, Лукаш Ланга (соавтор большинства типов хинтинга, включая PEP 563), заявляет:
ОК, поэтому я попробовал вышеизложенное, и кажется, что это ядерный вариант, так как он заставляет всеаннотации для оценки.Это то, чего я хотел избежать с помощью from __future__ import annotations
.
и в обсуждении по запросу на удаление, который исправил проблему 33453 , Эрик Смит, автор dataclasses
, заявил:
Я занимаюсь именно этим.Я думаю, что точка зрения @ ambv заключается в том, что она вводит снижение производительности из-за вызова eval для каждого поля, тогда как смысл строковых аннотаций состоит в том, чтобы удалять снижение производительности.
Кроме того, были другие проблемы;Вы не можете оценивать все подсказки типов во время импорта, а не тогда, когда они используют прямые ссылки:
В дополнение к проблеме производительности, в следующем случае (без оператора __future__
и без классов данных)Я получаю сообщение об ошибке get_type_hints()
, потому что C
не определено при вызове get_type_hints()
.Это python / набрав # 508 .Обратите внимание, что там, где в этом примере вызывается get_type_hints()
, именно там и будет выполняться @dataclass
, и ему нужно будет вызвать урезанное get_type_hints()
.
Итак, в конце концов, все это dataclasses
делает - это делает, применяет эвристику строк к аннотациям и не загружает их для вас.
Чтобы получить тип, просто используйте get_type_hints()
в самом классе и используйте атрибут field .name
как ключ к результату:
resolved = typing.get_type_hints(C)
f = dataclasses.fields(C)[0]
ftype = resolved[f.name]