ast.md
1> **Источник:** https://python-all.ru/3.8/library/ast.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# [`ast`](https://python-all.ru/3.8/library/ast.html#module-ast) – абстрактные синтаксические деревья89**Исходный код:** [Lib/ast.py](https://python-all.ru/src/3.8/Lib/ast.py)1011---1213Модуль [`ast`](https://python-all.ru/3.8/library/ast.html#module-ast) помогает приложениям Python обрабатывать деревья абстрактного синтаксиса языка Python. Абстрактный синтаксис может меняться от версии к версии; с помощью этого модуля можно программно узнать, как выглядит текущая грамматика.1415Абстрактное синтаксическое дерево можно создать, передав `ast.PyCF_ONLY_AST` в качестве флага встроенной функции [`compile()`](https://python-all.ru/3.8/library/functions.html#compile) или используя вспомогательную функцию [`parse()`](https://python-all.ru/3.8/library/ast.html#ast.parse) из этого модуля. Результатом будет дерево объектов, классы которых наследуют от [`ast.AST`](https://python-all.ru/3.8/library/ast.html#ast.AST). Абстрактное синтаксическое дерево можно скомпилировать в объект кода Python с помощью встроенной функции [`compile()`](https://python-all.ru/3.8/library/functions.html#compile).1617## Классы узлов1819#### `class ast.AST`2021Это базовый класс всех узлов AST. Конкретные классы узлов порождаются из файла `Parser/Python.asdl`, который воспроизведён [ниже](https://python-all.ru/3.8/library/ast.html#abstract-grammar). Они определены в C-модуле `_ast` и реэкспортированы в [`ast`](https://python-all.ru/3.8/library/ast.html#module-ast).2223Для каждого символа левой части абстрактной грамматики определён один класс (например, `ast.stmt` или `ast.expr`). Кроме того, для каждого конструктора правой части определён один класс; эти классы наследуют от классов для деревьев левой части. Например, `ast.BinOp` наследует от `ast.expr`. Для продукционных правил с альтернативами (так называемых «сумм») класс левой части является абстрактным: создаются только экземпляры конкретных узлов-конструкторов.2425#### `_fields`2627Каждый конкретный класс имеет атрибут [`_fields`](https://python-all.ru/3.8/library/ast.html#ast.AST._fields), который содержит имена всех дочерних узлов.2829Каждый экземпляр конкретного класса имеет по одному атрибуту для каждого дочернего узла, тип которого определён в грамматике. Например, экземпляры `ast.BinOp` имеют атрибут `left` типа `ast.expr`.3031Если эти атрибуты помечены как необязательные в грамматике (с помощью вопросительного знака), значением может быть `None`. Если атрибуты могут иметь ноль или более значений (помечены звёздочкой), значения представляются в виде списков Python. Все возможные атрибуты должны присутствовать и иметь корректные значения при компиляции AST с помощью [`compile()`](https://python-all.ru/3.8/library/functions.html#compile).3233#### `lineno`3435#### `col_offset`3637#### `end_lineno`3839#### `end_col_offset`4041Экземпляры подклассов `ast.expr` и `ast.stmt` имеют атрибуты [`lineno`](https://python-all.ru/3.8/library/ast.html#ast.AST.lineno), [`col_offset`](https://python-all.ru/3.8/library/ast.html#ast.AST.col_offset), [`lineno`](https://python-all.ru/3.8/library/ast.html#ast.AST.lineno) и [`col_offset`](https://python-all.ru/3.8/library/ast.html#ast.AST.col_offset). Атрибуты [`lineno`](https://python-all.ru/3.8/library/ast.html#ast.AST.lineno) и [`end_lineno`](https://python-all.ru/3.8/library/ast.html#ast.AST.end_lineno) – это номера первой и последней строк исходного текста (нумерация с 1, поэтому первая строка – строка 1), а [`col_offset`](https://python-all.ru/3.8/library/ast.html#ast.AST.col_offset) и [`end_col_offset`](https://python-all.ru/3.8/library/ast.html#ast.AST.end_col_offset) – это соответствующие смещения в байтах UTF-8 для первого и последнего токенов, породивших узел. Смещение в UTF-8 записывается, поскольку синтаксический анализатор использует UTF-8 внутри.4243Обратите внимание, что конечные позиции не требуются компилятором и поэтому являются необязательными. Смещение конца находится *после* последнего символа, например, можно получить фрагмент исходного кода узла выражения из одной строки с помощью `source_line[node.col_offset : node.end_col_offset]`.4445Конструктор класса `ast.T` разбирает свои аргументы следующим образом:4647- Если есть позиционные аргументы, их должно быть столько же, сколько элементов в `T._fields`; они будут присвоены как атрибуты с этими именами.48- Если есть ключевые аргументы, они установят атрибуты с теми же именами в указанные значения.4950Например, чтобы создать и заполнить узел `ast.UnaryOp`, можно использовать5152```python53node = ast.UnaryOp()54node.op = ast.USub()55node.operand = ast.Constant()56node.operand.value = 557node.operand.lineno = 058node.operand.col_offset = 059node.lineno = 060node.col_offset = 061```6263или более компактный6465```python66node = ast.UnaryOp(ast.USub(), ast.Constant(5, lineno=0, col_offset=0),67 lineno=0, col_offset=0)68```6970Изменено в версии 3.8: Класс `ast.Constant` теперь используется для всех констант.7172Устарело с версии 3.8: Старые классы `ast.Num`, `ast.Str`, `ast.Bytes`, `ast.NameConstant` и `ast.Ellipsis` всё ещё доступны, но будут удалены в будущих версиях Python. А пока создание их экземпляров будет возвращать экземпляр другого класса.7374## Абстрактная грамматика7576Абстрактная грамматика в настоящее время определяется следующим образом:7778```text79-- ASDL's 5 builtin types are:80-- identifier, int, string, object, constant8182module Python83{84 mod = Module(stmt* body, type_ignore *type_ignores)85 | Interactive(stmt* body)86 | Expression(expr body)87 | FunctionType(expr* argtypes, expr returns)8889 -- not really an actual node but useful in Jython's typesystem.90 | Suite(stmt* body)9192 stmt = FunctionDef(identifier name, arguments args,93 stmt* body, expr* decorator_list, expr? returns,94 string? type_comment)95 | AsyncFunctionDef(identifier name, arguments args,96 stmt* body, expr* decorator_list, expr? returns,97 string? type_comment)9899 | ClassDef(identifier name,100 expr* bases,101 keyword* keywords,102 stmt* body,103 expr* decorator_list)104 | Return(expr? value)105106 | Delete(expr* targets)107 | Assign(expr* targets, expr value, string? type_comment)108 | AugAssign(expr target, operator op, expr value)109 -- 'simple' indicates that we annotate simple name without parens110 | AnnAssign(expr target, expr annotation, expr? value, int simple)111112 -- use 'orelse' because else is a keyword in target languages113 | For(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment)114 | AsyncFor(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment)115 | While(expr test, stmt* body, stmt* orelse)116 | If(expr test, stmt* body, stmt* orelse)117 | With(withitem* items, stmt* body, string? type_comment)118 | AsyncWith(withitem* items, stmt* body, string? type_comment)119120 | Raise(expr? exc, expr? cause)121 | Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)122 | Assert(expr test, expr? msg)123124 | Import(alias* names)125 | ImportFrom(identifier? module, alias* names, int? level)126127 | Global(identifier* names)128 | Nonlocal(identifier* names)129 | Expr(expr value)130 | Pass | Break | Continue131132 -- XXX Jython will be different133 -- col_offset is the byte offset in the utf8 string the parser uses134 attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)135136 -- BoolOp() can use left & right?137 expr = BoolOp(boolop op, expr* values)138 | NamedExpr(expr target, expr value)139 | BinOp(expr left, operator op, expr right)140 | UnaryOp(unaryop op, expr operand)141 | Lambda(arguments args, expr body)142 | IfExp(expr test, expr body, expr orelse)143 | Dict(expr* keys, expr* values)144 | Set(expr* elts)145 | ListComp(expr elt, comprehension* generators)146 | SetComp(expr elt, comprehension* generators)147 | DictComp(expr key, expr value, comprehension* generators)148 | GeneratorExp(expr elt, comprehension* generators)149 -- the grammar constrains where yield expressions can occur150 | Await(expr value)151 | Yield(expr? value)152 | YieldFrom(expr value)153 -- need sequences for compare to distinguish between154 -- x < 4 < 3 and (x < 4) < 3155 | Compare(expr left, cmpop* ops, expr* comparators)156 | Call(expr func, expr* args, keyword* keywords)157 | FormattedValue(expr value, int? conversion, expr? format_spec)158 | JoinedStr(expr* values)159 | Constant(constant value, string? kind)160161 -- the following expression can appear in assignment context162 | Attribute(expr value, identifier attr, expr_context ctx)163 | Subscript(expr value, slice slice, expr_context ctx)164 | Starred(expr value, expr_context ctx)165 | Name(identifier id, expr_context ctx)166 | List(expr* elts, expr_context ctx)167 | Tuple(expr* elts, expr_context ctx)168169 -- col_offset is the byte offset in the utf8 string the parser uses170 attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)171172 expr_context = Load | Store | Del | AugLoad | AugStore | Param173174 slice = Slice(expr? lower, expr? upper, expr? step)175 | ExtSlice(slice* dims)176 | Index(expr value)177178 boolop = And | Or179180 operator = Add | Sub | Mult | MatMult | Div | Mod | Pow | LShift181 | RShift | BitOr | BitXor | BitAnd | FloorDiv182183 unaryop = Invert | Not | UAdd | USub184185 cmpop = Eq | NotEq | Lt | LtE | Gt | GtE | Is | IsNot | In | NotIn186187 comprehension = (expr target, expr iter, expr* ifs, int is_async)188189 excepthandler = ExceptHandler(expr? type, identifier? name, stmt* body)190 attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)191192 arguments = (arg* posonlyargs, arg* args, arg? vararg, arg* kwonlyargs,193 expr* kw_defaults, arg? kwarg, expr* defaults)194195 arg = (identifier arg, expr? annotation, string? type_comment)196 attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)197198 -- keyword arguments supplied to call (NULL identifier for **kwargs)199 keyword = (identifier? arg, expr value)200201 -- import name with optional 'as' alias.202 alias = (identifier name, identifier? asname)203204 withitem = (expr context_expr, expr? optional_vars)205206 type_ignore = TypeIgnore(int lineno, string tag)207}208```209210## [`ast`](https://python-all.ru/3.8/library/ast.html#module-ast) Вспомогательные функции211212Помимо классов узлов, модуль [`ast`](https://python-all.ru/3.8/library/ast.html#module-ast) определяет следующие служебные функции и классы для обхода абстрактных синтаксических деревьев:213214#### `ast.parse(source, filename='<unknown>', mode='exec', *, type_comments=False, feature_version=None)`215216Разбирает исходный код в узел AST. Эквивалентно `compile(source, filename, mode, ast.PyCF_ONLY_AST)`.217218Если задан `type_comments=True`, парсер изменяется, чтобы проверять и возвращать комментарии типов, как указано в [**PEP 484**](https://python-all.ru/3.8/library/ast.html) и [**PEP 526**](https://python-all.ru/3.8/library/ast.html). Это эквивалентно добавлению `ast.PyCF_TYPE_COMMENTS` к флагам, передаваемым в [`compile()`](https://python-all.ru/3.8/library/functions.html#compile). Это приведёт к сообщению об ошибках синтаксиса для неправильно расположенных комментариев типов. Без этого флага комментарии типов будут игнорироваться, и поле `type_comment` в выбранных узлах AST всегда будет `None`. Кроме того, расположение комментариев `# type: ignore` будет возвращаться как атрибут `type_ignores` объекта `Module` (иначе это всегда пустой список).219220Кроме того, если `mode` равно `'func_type'`, синтаксис входных данных изменяется в соответствии с [**PEP 484**](https://python-all.ru/3.8/library/ast.html) «сигнатурными комментариями типов», например `(str, int) -> List[str]`.221222Также установка `feature_version` в кортеж `(major, minor)` попытается выполнить разбор с использованием грамматики этой версии Python. В настоящее время `major` должно быть равно `3`. Например, установка `feature_version=(3, 4)` разрешит использование `async` и `await` в качестве имён переменных. Минимальная поддерживаемая версия – `(3, 4)`; максимальная – `sys.version_info[0:2]`.223224> **Предупреждение**225>226> Можно вызвать сбой интерпретатора Python с помощью достаточно большой/сложной строки из-за ограничений глубины стека в компиляторе AST Python.227228Изменено в версии 3.8: Добавлены `type_comments`, `mode='func_type'` и `feature_version`.229230#### `ast.literal_eval(node_or_string)`231232Безопасно вычисляет узел выражения или строку, содержащую литерал Python или отображение контейнера. Предоставленная строка или узел могут состоять только из следующих литеральных структур Python: строки, байты, числа, кортежи, списки, словари, множества, логические значения и `None`.233234Это можно использовать для безопасного вычисления строк, содержащих значения Python из ненадёжных источников, без необходимости разбирать значения самостоятельно. Он не способен вычислять произвольно сложные выражения, например с операторами или индексацией.235236> **Предупреждение**237>238> Можно вызвать сбой интерпретатора Python с помощью достаточно большой/сложной строки из-за ограничений глубины стека в компиляторе AST Python.239240Изменено в версии 3.2: Теперь допускает литералы байтов и множеств.241242#### `ast.get_docstring(node, clean=True)`243244Возвращает строку документации для данного *узла* (который должен быть узлом `FunctionDef`, `AsyncFunctionDef`, `ClassDef` или `Module`) или `None`, если у него нет строки документации. Если *clean* истинно, очищает отступы строки документации с помощью [`inspect.cleandoc()`](https://python-all.ru/3.8/library/inspect.html#inspect.cleandoc).245246Изменено в версии 3.5: Теперь поддерживается `AsyncFunctionDef`.247248#### `ast.get_source_segment(source, node, *, padded=False)`249250Возвращает фрагмент исходного кода из *source*, который породил узел *node*. Если не хватает информации о местоположении (`lineno`, `end_lineno`, `col_offset` или `end_col_offset`), возвращает `None`.251252Если *padded* равно `True`, первая строка многострочного оператора будет дополнена пробелами, чтобы соответствовать исходной позиции.253254Новое в версии 3.8.255256#### `ast.fix_missing_locations(node)`257258При компиляции дерева узлов с помощью [`compile()`](https://python-all.ru/3.8/library/functions.html#compile) компилятор ожидает атрибуты `lineno` и `col_offset` для каждого узла, который их поддерживает. Заполнять их вручную для сгенерированных узлов довольно утомительно, поэтому эта вспомогательная функция рекурсивно добавляет эти атрибуты, если их ещё нет, устанавливая их равными значениям родительского узла. Работает рекурсивно, начиная с *node*.259260#### `ast.increment_lineno(node, n=1)`261262Увеличивает номер строки и номер конечной строки каждого узла в дереве, начиная с *node*, на *n*. Это полезно для «перемещения кода» в другое место в файле.263264#### `ast.copy_location(new_node, old_node)`265266Копирует информацию о местоположении в исходном коде (`lineno`, `col_offset`, `end_lineno` и `end_col_offset`) из *old\_node* в *new\_node*, если это возможно, и возвращает *new\_node*.267268#### `ast.iter_fields(node)`269270Генерирует кортеж из `(fieldname, value)` для каждого поля в `node._fields`, которое присутствует в *node*.271272#### `ast.iter_child_nodes(node)`273274Генерирует все непосредственные дочерние узлы *node*, то есть все поля, являющиеся узлами, и все элементы полей, являющихся списками узлов.275276#### `ast.walk(node)`277278Рекурсивно генерирует все узлы-потомки в дереве, начиная с *node* (включая сам *node*), в произвольном порядке. Это полезно, если требуется только изменить узлы на месте, а контекст не важен.279280#### `class ast.NodeVisitor`281282Базовый класс для обхода узлов, который обходит абстрактное синтаксическое дерево и вызывает функцию-посетитель для каждого найденного узла. Эта функция может вернуть значение, которое передаётся методом [`visit()`](https://python-all.ru/3.8/library/ast.html#ast.NodeVisitor.visit).283284Этот класс предназначен для наследования; в подклассе добавляются методы-посетители.285286#### `visit(node)`287288Посещает узел. Реализация по умолчанию вызывает метод `self.visit_classname`, где *classname* – имя класса узла, или [`generic_visit()`](https://python-all.ru/3.8/library/ast.html#ast.NodeVisitor.generic_visit), если такой метод отсутствует.289290#### `generic_visit(node)`291292Этот посетитель вызывает [`visit()`](https://python-all.ru/3.8/library/ast.html#ast.NodeVisitor.visit) для всех дочерних узлов.293294Обратите внимание, что дочерние узлы тех узлов, для которых определён собственный метод-посетитель, не будут посещены, если посетитель сам не вызовет [`generic_visit()`](https://python-all.ru/3.8/library/ast.html#ast.NodeVisitor.generic_visit) или не обойдёт их самостоятельно.295296Не используйте [`NodeVisitor`](https://python-all.ru/3.8/library/ast.html#ast.NodeVisitor), если требуется вносить изменения в узлы во время обхода. Для этого существует специальный посетитель ([`NodeTransformer`](https://python-all.ru/3.8/library/ast.html#ast.NodeTransformer)), который допускает модификации.297298Устарело с версии 3.8: Методы `visit_Num()`, `visit_Str()`, `visit_Bytes()`, `visit_NameConstant()` и `visit_Ellipsis()` теперь устарели и не будут вызываться в будущих версиях Python. Добавьте метод `visit_Constant()` для обработки всех узлов-констант.299300#### `class ast.NodeTransformer`301302Подкласс [`NodeVisitor`](https://python-all.ru/3.8/library/ast.html#ast.NodeVisitor), который обходит абстрактное синтаксическое дерево и позволяет изменять узлы.303304Метод [`NodeTransformer`](https://python-all.ru/3.8/library/ast.html#ast.NodeTransformer) обходит AST и использует возвращаемое значение методов-посетителей для замены или удаления старого узла. Если возвращаемое значение метода-посетителя равно `None`, узел будет удалён из своего местоположения; в противном случае он заменяется возвращённым значением. Возвращённое значение может быть исходным узлом – в этом случае замена не происходит.305306Вот пример преобразователя, который переписывает все обращения к именам (`foo`) в `data['foo']`:307308```python309class RewriteName(NodeTransformer):310311 def visit_Name(self, node):312 return Subscript(313 value=Name(id='data', ctx=Load()),314 slice=Index(value=Constant(value=node.id)),315 ctx=node.ctx316 )317```318319Имейте в виду: если у узла, с которым вы работаете, есть дочерние узлы, необходимо либо преобразовать дочерние узлы самостоятельно, либо сначала вызвать для узла метод `generic_visit()`.320321Для узлов, входящих в состав набора инструкций (это относится ко всем узлам инструкций), посетитель может также возвращать список узлов, а не один узел.322323Если [`NodeTransformer`](https://python-all.ru/3.8/library/ast.html#ast.NodeTransformer) вводит новые узлы (не входившие в исходное дерево) без указания информации о расположении (например, `lineno`), следует вызвать [`fix_missing_locations()`](https://python-all.ru/3.8/library/ast.html#ast.fix_missing_locations) для нового поддерева, чтобы пересчитать информацию о расположении:324325```python326tree = ast.parse('foo', mode='eval')327new_tree = fix_missing_locations(RewriteName().visit(tree))328```329330Обычно преобразователь используется следующим образом:331332```python333node = YourTransformer().visit(node)334```335336#### `ast.dump(node, annotate_fields=True, include_attributes=False)`337338Возвращает форматированный дамп дерева из *node*. Это в основном полезно для отладки. Если *annotate\_fields* равно true (по умолчанию), возвращаемая строка будет показывать имена и значения полей. Если *annotate\_fields* равно false, результирующая строка будет более компактной за счёт опускания однозначных имён полей. Атрибуты, такие как номера строк и смещения столбцов, по умолчанию не выводятся. Если это нужно, *include\_attributes* можно установить в true.339340> **См. также**341>342> [Green Tree Snakes](https://python-all.ru/3.8/library/ast.html) – внешний документационный ресурс, содержащий подробности работы с AST Python.343>344> [ASTTokens](https://python-all.ru/3.8/library/ast.html) дополняет AST Python позициями токенов и текста в исходном коде, который их породил. Это полезно для инструментов, выполняющих преобразования исходного кода.345>346> [leoAst.py](https://python-all.ru/3.8/library/ast.html) объединяет представления программ на Python на основе токенов и синтаксических деревьев, вставляя двусторонние связи между токенами и узлами AST.347>348> [LibCST](https://python-all.ru/3.8/library/ast.html) разбирает код как конкретное синтаксическое дерево, похожее на AST, и сохраняет все детали форматирования. Это полезно для создания приложений автоматического рефакторинга (codemod) и линтеров.349>350> [Parso](https://python-all.ru/3.8/library/ast.html) – это синтаксический анализатор Python, поддерживающий восстановление после ошибок и сквозной разбор для разных версий Python (на нескольких версиях Python). Parso также может перечислять несколько синтаксических ошибок в файле Python.351