- Аннотация
- Мотивация
- Спецификация Размещение докстринга Поведение во время выполнения Оптимизация Поддержка AST Поддержка стандартной библиотеки
- Размещение докстринга
- Поведение во время выполнения
- Оптимизация
- Поддержка AST
- Поддержка стандартной библиотеки
- Обоснование
- Обратная совместимость
- Влияние на безопасность
- Как этому обучать
- Эталонная реализация
- Отклоненные идеи Сохранение строкового выражения
- Сохранение строкового выражения
- Благодарности
- История изменений
Аннотация
Данный PEP предлагает сохранять строковый литерал, следующий сразу за инструкцией type, в качестве атрибута __doc__ результирующего объекта псевдонима типа, делая эту документацию доступной через ast и отображая её посредством pydoc и help(). Это соответствует правилам размещения, которые уже поддерживаются инструментами документирования на основе исходного кода. Парсер сохраняет докстринг в новом необязательном поле doc узла ast.TypeAlias вместо создания для него отдельного узла ast.Expr. Функция ast.get_docstring() извлекает докстринги псевдонимов из этого поля.
Мотивация
Несколько широко используемых инструментов разработки уже распознают докстринги, следующие за объявлениями псевдонимов типов. Pyright поддерживает докстринги, следующие за инструкциями type (начиная с 2023 года), директива autotype в Sphinx документирует псевдонимы и их докстринги (начиная с 2025 года), а Pylint распознает эти строки как документацию (начиная с 2023 года).
Например, псевдоним может пояснять, как вызывающий код должен интерпретировать его значения:
Вызов отображает общую информацию о TypeAliasType , а не докстринг псевдонима. Инструменту, которому требуется документация псевдонима, приходится находить и анализировать его исходный код, который может быть недоступен после установки или когда псевдоним передается из другого компонента.
Инструкция , введенная в PEP 695, создает специализированный объект во время выполнения. Этот объект может содержать собственную документацию, как функции и классы. Сохранение докстринга сделает его доступным непосредственно из импортированного псевдонима, в том числе при его повторном экспорте.
Документация во время выполнения также может использоваться сторонними фреймворками. Фреймворки, которые уже распознают (например, Pydantic), могут использовать __doc__ в качестве описательных метаданных. Подобные интеграции остаются на усмотрение этих проектов.
Спецификация
Размещение докстринга
PEP 257 определяет соглашение о размещении докстрингов атрибутов сразу после присваиваний и называет строки, идущие после другого докстринга, «дополнительными докстрингами». Этот PEP использует то же соглашение о размещении для инструкций : строковый литерал, следующий сразу за инструкцией, становится докстринг псевдонима.
Если следующая логическая строка после инструкции в том же блоке является выражением-инструкцией, состоящим из строкового литерала, эта строка является докстрингом псевдонима и частью инструкции type. Между инструкцией type и её докстринг могут находиться комментарии и пустые строки. Строковый литерал на той же строке, что и псевдоним, отделенный точкой с запятой, не подходит.
Это правило применяется везде, где разрешена инструкция , включая функции, классы и блоки управления потоком. Строка должна находиться в том же блоке, что и псевдоним. Строка во вложенном или внешнем блоке не подходит. Общие псевдонимы следуют тому же правилу:
Как и для модулей, функций и классов, докстринг должен быть выражением-инструкцией, значением которого является строковая константа. Подходят соседние строковые литералы, объединенные парсером, а также заключенный в круглые скобки строковый литерал. Байтовые литералы, f-строки, t-строки и выражения вроде "first" + "second" не подходят, даже если компиляция может свести выражение к константной строке.
Только первое следующее строковое выражение предоставляет __doc__. Дополнительные докстринги в понимании PEP 257 остаются обычными выражениями-инструкциями. Они не конкатенируются и не присваиваются псевдониму.
Поведение во время выполнения
Псевдоним сохраняет свой докстринг в атрибуте __doc__. У недокументированного псевдонима __doc__ равен None. Доступ к этому атрибуту не вычисляет значение псевдонима.
Компиляция применяет к докстрингу ту же обработку пробелов, что и для докстрингов функций и классов. Это разворачивает табуляции и очищает отступы, сохраняя при этом окружающие пустые строки. inspect.cleandoc() также удаляет окружающие пустые строки.
После создания псевдонима его атрибут __doc__ может быть переназначен. Его удаление сбрасывает значение в None. Конструктор получает новый параметр doc, доступный только по ключевому слову, со значением по умолчанию None, который инициализирует __doc__ без обработки пробелов:
Данное предложение не требует каких-либо изменений в поведении проверки типов. Докстринг псевдонима не влияет на его значение для проверки типов или на то, как его значение вычисляется во время выполнения.
Оптимизация
Уровень оптимизации 2, выбираемый с помощью -OO или , удаляет докстринги псевдонимов точно так же, как удаляет докстринги функций и классов. Полученный псевдоним имеет __doc__, равный None. В AST предварительная обработка очищает поле doc объекта . Уровни оптимизации 0 и 1 сохраняют докстринг.
Присваивания __doc__ остаются обычными присваиваниями во время выполнения и не удаляются оптимизатором .
Поддержка AST
Грамматика инструкции получает необязательный хвостовой докстринг, показанный схематично:
Здесь type_alias_docstring обозначает выражение-инструкцию, значением которого является строковая константа, как определено в разделе «Размещение докстринга».
Данный PEP добавляет необязательное строковое поле doc в конец (name, type_params, value, doc). Пропущенное поле doc по умолчанию имеет значение None.
Когда докстринги сохраняются, заполняет это поле исходной строкой до обработки пробелов при компиляции. Докстринг не появляется как последующий узел Expr(Constant(...)). Конечная позиция узла охватывает докстринг:
принимает узлы TypeAlias. Как и для уже поддерживаемых типов узлов, его поведение по умолчанию очищает докстринг с помощью . При clean=False функция возвращает исходную строку. Для недокументированного псевдонима она возвращает None.
И , и AST отображают докстринг в поле doc. По умолчанию ast.dump() опускает это поле, когда его значение равно None, как и для других необязательных полей.
Генерация кода считывает поле doc и не проверяет соседние инструкции. Для программно сконструированных узлов поле doc предоставляет докстринг псевдонима. Функция ast.unparse() выводит докстринг в виде строковой инструкции на строке после псевдонима, так что синтаксический анализ результата снова заполнит это поле.
Поддержка стандартной библиотеки
, включая , будет распознавать псевдонимы типов и отображать их собственную документацию. Псевдонимы также будут отличаться от других членов данных в документации модуля. Это относится как к текстовому выводу, так и к выводу в формате HTML.
Для примера в начале эталонная реализация отображает:
doctest обнаруживает докстринги псевдонимов типов в модулях и классах, а также принимает объекты псевдонимов типов в словаре __test__ модуля. Как и в случае функций и классов, псевдонимы, импортированные из других модулей, исключаются из автоматического обнаружения. Обнаружение не вычисляет значения псевдонимов.
Обоснование
Размещение строки после объявления соответствует соглашению, которое уже используется инструментами для псевдонимов типов и описано для строк документации атрибутов в PEP 257. Существующие документированные псевдонимы получат документацию во время выполнения без необходимости переписывать их для авторов.
Сохранение строки документации в поле doc узла псевдонима позволяет извлекать ее без поиска по окружающим инструкциям. Инструменты, которые проверяют или изменяют строки документации псевдонимов, могут напрямую читать или обновлять это поле. Платой за это является изменение AST, описанное в разделе «Обратная совместимость».
Обратная совместимость
Ранее строковый литерал, следующий сразу за инструкцией , не оказывал никакого влияния во время выполнения. Согласно данному предложению, подходящая строка становится атрибутом __doc__ псевдонима и удаляется из AST в качестве отдельной инструкции . Строка сохраняется в поле doc узла псевдонима, а конечная позиция узла расширяется, чтобы охватить ее.
Инструменты, которые находят строки документации псевдонимов, обращаясь к следующей инструкции, или которые полагаются на конечную позицию узла псевдонима, нуждаются в доработке при синтаксическом анализе с помощью Python 3.16. получает четвертое необязательное поле. Создание узла с тремя позиционными аргументами продолжает работать.
Влияние на безопасность
Этот PEP не имеет известных последствий для безопасности.
Как этому обучать
Справочная документация по инструкции должна показывать строку документации сразу после объявления, отмечать, что принятые формы соответствуют строкам документации функций и классов, а затем демонстрировать Alias.__doc__ и . Документация должна описывать новый атрибут и способы его присвоения для псевдонимов, созданных с помощью конструктора.
Пользователи, уже знакомые с документированием псевдонимов на основе исходного кода, могут продолжать писать те же строки. В документации следует подчеркнуть, что строки документации в период выполнения получают только инструкции . Обычные присваивания, включая те, что аннотированы с помощью , — нет.
Документация для и ast.get_docstring() должна объяснять, как читать и модифицировать поле doc и как обрабатываются пробелы. В ней также следует отметить, что строка документации больше не имеет отдельного узла ast.Expr.
Эталонная реализация
Прототип CPython доступен по следующим ревизиям:
Правило грамматики для инструкции получает необязательную группу, которая разбирает инструкцию выражения на следующей логической строке. Правило type_alias_docstring[expr_ty] использует вспомогательное действие, которое возвращает узел выражения, если он является строковой константой. В противном случае вспомогательная функция возвращает NULL, не устанавливая ошибку. Это приводит к сбою необязательной группы, поэтому синтаксический анализатор возвращается к моменту до перевода строки. Пустые строки и строки, содержащие только комментарии, не мешают синтаксическому анализатору распознать строку документации. Строка должна находиться в том же блоке, что и инструкция типа. Действие с псевдонимом типа извлекает строковое значение константы и сохраняет его в поле doc.
Реализация запрашивает выражение псевдонима в строковом формате. Это вычисление может инициировать ленивый импорт. Если вычисление вызывает Exception, pydoc пытается восстановить исходное выражение псевдонима из исходного кода без его вычисления. Если восстановление из исходного кода также не удается, объявление содержит заполнитель с исходного исключения, и отрисовка продолжается со строкой документации. Полная трассировка не включается. Ошибки при отрисовке границ параметров типа, ограничений или значений по умолчанию приводят к тому, что эта часть объявления опускается.
Отвергнутые идеи
Сохранение строковой инструкции
Альтернативный дизайн предполагал бы, что предварительная обработка AST заполняет поле doc, сохраняя при этом строку в качестве отдельной инструкции , следующей за псевдонимом. Существующие инструменты могли бы продолжать проверять эту инструкцию, но AST содержал бы одну и ту же документацию как в поле, так и в инструкции. После преобразования AST эти два элемента могли бы содержать разные строки. В таком случае компилятору потребовалось бы правило для выбора используемой строки. Функции ast.unparse() и также могли бы создавать разные строки документации из одного и того же дерева, если бы использовали разные копии.
При удалении строки документации в соответствии с предварительная обработка AST также должна была бы предотвращать занятие ее места другой строкой документации в случае повторной компиляции дерева. При распознавании на уровне синтаксического анализатора AST содержит строку документации только в поле doc, поэтому такие правила не нужны.
В одном варианте поле doc ссылалось бы на исходный узел . Изменения на месте были бы видны через обе ссылки, но посетители доходили бы до одного и того же узла дважды. Замена узла через одну ссылку оставляла бы другую ссылку указывающей на старый узел.
В другом варианте частный атрибут содержал бы строку документации, доступную только через . Такой дизайн позволил бы избежать публичного поля, но предварительной обработке AST все равно потребовались бы правила для аннулирования сохраненной документации при изменении окружающих инструкций.
Благодарности
Спасибо Йелле Зейлстре (Jelle Zijlstra) за рецензирование предложения и согласие спонсировать этот PEP, Гвидо ван Россуму (Guido van Rossum) за предложение сделать так, чтобы синтаксический анализатор распознавал строку документации, а также участникам первоначального обсуждения на Discourse.
Спасибо Питеру Бирме (Peter Bierma) и Якубу Романчуку (Jakub Romańczuk) за то, что убедили меня заняться этой идеей.
История изменений
- 06-Sep-2026: Первоначальное предложение и первый черновик PEP.
- 15-сен-2026: Синтаксический анализатор распознает строку документации как часть инструкции , а не через предварительную обработку AST, связывающую следующую инструкцию с псевдонимом. AST больше не сохраняет строку в качестве отдельной инструкции.
Этот документ передается в общественное достояние или под лицензию CC0-1.0-Universal, в зависимости от того, какая из них является более мягкой.







