Как from __future__ import annotations влияет на __annotations__

Как from __future__ import annotations влияет на __annotations__

@python_quiz

Разберем этот квиз

Коротко — в примере аннотации сохраняются не как объекты типов, а как строки. Ниже разберём код, покажем вывод и проанализируем возможные варианты ответа.

Исходный код

python

Этот фрагмент присутствовал в условии квиза. Обратите внимание на from __future__ import annotations и на использование | для объединения типов (PEP 604).

Что делает from __future__ import annotations

  • Этот импорт включает отложенную (postponed) оценку аннотаций (PEP 563). Вместо реальных объектов типов в __annotations__ сохраняются строковые представления исходных аннотаций.
  • Это полезно, чтобы избежать импортных зависимостей во время определения функций/классов и ускорить время импорта.
  • Для получения "реальных" объектов типов из таких строк используют typing.get_type_hints() (он выполнит безопасную оценку аннотаций).

Ожидаемый вывод

При запуске приведённого кода __annotations__ будет выглядеть так:

python

То есть значения в словаре — строки с текстовым представлением аннотаций, а не сами объекты типа int или объединённого типа int | str.

Анализ вариантов ответа

Допустим, в квизе были такие варианты (привожу их как текст):

  • {'x': int, 'y': int, 'return': int}

Пояснение: значения — объекты типа int. В рассматриваемом примере это неверно — аннотации описывают объединение int | str, да и при отложенной оценке они хранятся как строки.

  • {'x': 'int | str', 'y': 'int | str', 'return': 'int | str'}

Пояснение: строки с текстовым представлением аннотаций. Это именно то, что сохраняется в __annotations__, когда включён from __future__ import annotations.

  • {'x': int | str, 'y': int | str, 'return': int | str}

Пояснение: объекты объединённого типа (PEP 604). Такой результат мог бы наблюдаться, если бы аннотации не были отложены и Python при парсинге создал бы реальные объекты объединений. Но с отложенной оценкой в __annotations__ попадут строки, а не вычисленные объекты.

  • {}

Пояснение: пустой словарь. Появляется только если аннотаций нет или они удалены; в нашем примере аннотации явно присутствуют, так что этот вариант не соответствует реальности.

Как получить реальные типы из отложённых аннотаций

Если нужно преобразовать строковые аннотации в реальные объекты типов, используют typing.get_type_hints():

python

Примерный вывод при исполнении на Python 3.10+:

python

Замечания:

  • Чтобы get_type_hints() корректно преобразовал выражения, интерпретатор должен понимать используемый синтаксис аннотаций (например, | для объединения требует Python 3.10+).
  • При сложных аннотациях (ссылающихся на имена из других модулей) get_type_hints() может потребовать корректные глобальные/локальные пространства имён или импортов.

Вывод

  • from __future__ import annotations заставляет Python сохранять аннотации как строки в __annotations__.
  • Поэтому в рассматриваемом примере словарь __annotations__ содержит строковые записи вида 'int | str'.
  • Для получения реальных объектов типов используйте typing.get_type_hints().

Report Page