Документация Python неофициальный перевод

ast.md

427 строк · 19.8 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/3.0/library/ast.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# Абстрактные синтаксические деревья89Модуль `ast` помогает приложениям Python обрабатывать деревья грамматики абстрактного синтаксиса Python. Сам абстрактный синтаксис может меняться от версии к версии Python; этот модуль позволяет программно узнавать, как выглядит текущая грамматика.1011Абстрактное синтаксическое дерево можно получить, передав `ast.PyCF_ONLY_AST` в качестве флага встроенной функции [`compile()`](https://python-all.ru/3.0/library/functions.html#compile) или с помощью вспомогательной функции [`parse()`](https://python-all.ru/3.0/library/ast.html#ast.parse) из этого модуля. Результатом будет дерево объектов, все классы которых наследуют от [`ast.AST`](https://python-all.ru/3.0/library/ast.html#ast.AST). Абстрактное синтаксическое дерево можно скомпилировать в объект кода Python с помощью встроенной функции [`compile()`](https://python-all.ru/3.0/library/functions.html#compile).1213## Классы узлов1415#### `[ast.AST]class ast.AST`1617Это базовый класс для всех узлов AST. Фактические классы узлов порождаются из файла `Parser/Python.asdl`, который воспроизведён [*ниже*](https://python-all.ru/3.0/library/ast.html#abstract-grammar). Они определены в C-модуле `_ast` и повторно экспортируются в `ast`.1819Для каждого символа левой части абстрактной грамматики определён один класс (например, `ast.stmt` или `ast.expr`). Кроме того, для каждого конструктора правой части определён один класс; эти классы наследуют от классов левой части. Например, `ast.BinOp` наследует от `ast.expr`. Для правил вывода с альтернативами (так называемых «сумм») класс левой части является абстрактным: создаются только экземпляры конкретных конструкторных узлов.2021#### `[ast.AST._fields]_fields`2223Каждый конкретный класс имеет атрибут [`_fields`](https://python-all.ru/3.0/library/ast.html#ast.AST._fields), который содержит имена всех дочерних узлов.2425Каждый экземпляр конкретного класса имеет по одному атрибуту для каждого дочернего узла, тип которого определён грамматикой. Например, экземпляры `ast.BinOp` имеют атрибут `left` типа `ast.expr`.2627Если эти атрибуты помечены как необязательные в грамматике (с помощью вопросительного знака), их значением может быть `None`. Если атрибуты могут иметь ноль или более значений (помечены звёздочкой), значения представляются в виде списков Python. Все возможные атрибуты должны присутствовать и иметь допустимые значения при компиляции AST с помощью [`compile()`](https://python-all.ru/3.0/library/functions.html#compile).2829#### `[ast.AST.lineno]lineno`3031#### `col_offset`3233Экземпляры подклассов3435`ast.expr`3637и3839`ast.stmt`4041имеют атрибуты4243[`lineno`](https://python-all.ru/3.0/library/ast.html#ast.AST.lineno)4445и4647[`col_offset`](https://python-all.ru/3.0/library/ast.html#ast.AST.col_offset)4849.5051[`lineno`](https://python-all.ru/3.0/library/ast.html#ast.AST.lineno)5253– это номер строки исходного текста (нумерация с 1, так что первая строка – строка 1), а5455[`col_offset`](https://python-all.ru/3.0/library/ast.html#ast.AST.col_offset)5657– это смещение в байтах UTF-8 первого токена, породившего узел. Смещение в UTF-8 записывается, потому что парсер использует UTF-8 внутри.5859Конструктор класса `ast.T` разбирает свои аргументы следующим образом:6061- Если есть позиционные аргументы, их должно быть столько же, сколько элементов в `T._fields`; они будут присвоены как атрибуты с этими именами.62- Если есть ключевые аргументы, они установят атрибуты с теми же именами в указанные значения.6364Например, чтобы создать и заполнить узел `ast.UnaryOp`, можно использовать6566```python67node = ast.UnaryOp()68node.op = ast.USub()69node.operand = ast.Num()70node.operand.n = 571node.operand.lineno = 072node.operand.col_offset = 073node.lineno = 074node.col_offset = 075```7677или более компактный7879```python80node = ast.UnaryOp(ast.USub(), ast.Num(5, lineno=0, col_offset=0),81                   lineno=0, col_offset=0)82```8384## Абстрактная грамматика8586Модуль определяет строковую константу `__version__`, которая содержит десятичный номер ревизии Subversion файла, показанного ниже.8788Абстрактная грамматика в настоящее время определяется следующим образом:8990```python91-- ASDL's four builtin types are identifier, int, string, object9293module Python version "$Revision: 67644 $"94{95	mod = Module(stmt* body)96	    | Interactive(stmt* body)97	    | Expression(expr body)9899	    -- not really an actual node but useful in Jython's typesystem.100	    | Suite(stmt* body)101102	stmt = FunctionDef(identifier name, arguments args, 103                           stmt* body, expr* decorator_list, expr? returns)104	      | ClassDef(identifier name, 105			 expr* bases,106			 keyword* keywords,107			 expr? starargs,108			 expr? kwargs,109			 stmt* body,110			 expr *decorator_list)111	      | Return(expr? value)112113	      | Delete(expr* targets)114	      | Assign(expr* targets, expr value)115	      | AugAssign(expr target, operator op, expr value)116117	      -- use 'orelse' because else is a keyword in target languages118	      | For(expr target, expr iter, stmt* body, stmt* orelse)119	      | While(expr test, stmt* body, stmt* orelse)120	      | If(expr test, stmt* body, stmt* orelse)121	      | With(expr context_expr, expr? optional_vars, stmt* body)122123	      | Raise(expr? exc, expr? cause)124	      | TryExcept(stmt* body, excepthandler* handlers, stmt* orelse)125	      | TryFinally(stmt* body, stmt* finalbody)126	      | Assert(expr test, expr? msg)127128	      | Import(alias* names)129	      | ImportFrom(identifier module, alias* names, int? level)130131	      | Global(identifier* names)132	      | Nonlocal(identifier* names)133	      | Expr(expr value)134	      | Pass | Break | Continue135136	      -- XXX Jython will be different137	      -- col_offset is the byte offset in the utf8 string the parser uses138	      attributes (int lineno, int col_offset)139140	      -- BoolOp() can use left & right?141	expr = BoolOp(boolop op, expr* values)142	     | BinOp(expr left, operator op, expr right)143	     | UnaryOp(unaryop op, expr operand)144	     | Lambda(arguments args, expr body)145	     | IfExp(expr test, expr body, expr orelse)146	     | Dict(expr* keys, expr* values)147	     | Set(expr* elts)148	     | ListComp(expr elt, comprehension* generators)149	     | SetComp(expr elt, comprehension* generators)150	     | DictComp(expr key, expr value, comprehension* generators)151	     | GeneratorExp(expr elt, comprehension* generators)152	     -- the grammar constrains where yield expressions can occur153	     | Yield(expr? value)154	     -- need sequences for compare to distinguish between155	     -- x < 4 < 3 and (x < 4) < 3156	     | Compare(expr left, cmpop* ops, expr* comparators)157	     | Call(expr func, expr* args, keyword* keywords,158			 expr? starargs, expr? kwargs)159	     | Num(object n) -- a number as a PyObject.160	     | Str(string s) -- need to specify raw, unicode, etc?161	     | Bytes(string s)162	     | Ellipsis163	     -- other literals? bools?164165	     -- the following expression can appear in assignment context166	     | Attribute(expr value, identifier attr, expr_context ctx)167	     | Subscript(expr value, slice slice, expr_context ctx)168	     | Starred(expr value, expr_context ctx)169	     | Name(identifier id, expr_context ctx)170	     | List(expr* elts, expr_context ctx) 171	     | Tuple(expr* elts, expr_context ctx)172173	      -- col_offset is the byte offset in the utf8 string the parser uses174	      attributes (int lineno, int col_offset)175176	expr_context = Load | Store | Del | AugLoad | AugStore | Param177178	slice = Slice(expr? lower, expr? upper, expr? step) 179	      | ExtSlice(slice* dims) 180	      | Index(expr value) 181182	boolop = And | Or 183184	operator = Add | Sub | Mult | Div | Mod | Pow | LShift 185                 | RShift | BitOr | BitXor | BitAnd | FloorDiv186187	unaryop = Invert | Not | UAdd | USub188189	cmpop = Eq | NotEq | Lt | LtE | Gt | GtE | Is | IsNot | In | NotIn190191	comprehension = (expr target, expr iter, expr* ifs)192193	-- not sure what to call the first argument for raise and except194	excepthandler = ExceptHandler(expr? type, identifier? name, stmt* body)195	                attributes (int lineno, int col_offset)196197	arguments = (arg* args, identifier? vararg, expr? varargannotation,198                     arg* kwonlyargs, identifier? kwarg,199                     expr? kwargannotation, expr* defaults,200                     expr* kw_defaults)201	arg = (identifier arg, expr? annotation)202203        -- keyword arguments supplied to call204        keyword = (identifier arg, expr value)205206        -- import name with optional 'as' alias.207        alias = (identifier name, identifier? asname)208}209```210211## `ast` Вспомогательные функции212213Помимо классов узлов, модуль `ast` определяет следующие вспомогательные функции и классы для обхода абстрактных синтаксических деревьев:214215#### `[ast.parse]ast.parse(expr, filename='<unknown>', mode='exec')`216217Разбирает выражение в узел AST. Эквивалентно218219`compile(expr, filename, mode, ast.PyCF_ONLY_AST)`220221.222223#### `[ast.literal_eval]ast.literal_eval(node_or_string)`224225Безопасно вычисляет узел выражения или строку, содержащую выражение Python. Предоставленная строка или узел может содержать только следующие литеральные структуры Python: строки, числа, кортежи, списки, словари, логические значения и `None`.226227Это можно использовать для безопасного вычисления строк, содержащих выражения Python из ненадёжных источников, без необходимости самостоятельно их разбирать.228229#### `[ast.get_docstring]ast.get_docstring(node, clean=True)`230231Возвращает docstring заданного232233*node*234235(который должен быть узлом236237`FunctionDef`238239,240241`ClassDef`242243или244245`Module`246247), или248249`None`250251, если docstring нет. Если252253*clean*254255равно True, очищает отступы docstring с помощью256257[`inspect.cleandoc()`](https://python-all.ru/3.0/library/inspect.html#inspect.cleandoc)258259.260261#### `[ast.fix_missing_locations]ast.fix_missing_locations(node)`262263При компиляции дерева узлов с помощью264265[`compile()`](https://python-all.ru/3.0/library/functions.html#compile)266267компилятор ожидает атрибуты268269`lineno`270271и272273`col_offset`274275для каждого узла, который их поддерживает. Заполнять их вручную для сгенерированных узлов довольно утомительно, поэтому эта вспомогательная функция рекурсивно добавляет эти атрибуты, если они ещё не установлены, присваивая им значения родительского узла. Она работает рекурсивно, начиная с276277*node*278279.280281#### `[ast.increment_lineno]ast.increment_lineno(node, n=1)`282283Увеличить номер строки каждого узла в дереве, начиная с284285*node*286287, на288289*n*290291. Это полезно для «переноса кода» в другое место в файле.292293#### `[ast.copy_location]ast.copy_location(new_node, old_node)`294295Копирует информацию о положении в исходном коде (296297`lineno`298299и300301`col_offset`302303) из304305*old\_node*306307в308309*new\_node*310311, если это возможно, и возвращает312313*new\_node*314315.316317#### `[ast.iter_fields]ast.iter_fields(node)`318319Генерирует кортеж320321`(fieldname, value)`322323для каждого поля из324325`node._fields`326327, которое присутствует в328329*node*330331.332333#### `[ast.iter_child_nodes]ast.iter_child_nodes(node)`334335Генерирует все непосредственные дочерние узлы336337*node*338339, то есть все поля, являющиеся узлами, и все элементы полей, являющихся списками узлов.340341#### `[ast.walk]ast.walk(node)`342343Рекурсивно выдаёт все дочерние узлы344345*node*346347в произвольном порядке. Это полезно, если требуется только изменить узлы на месте, не заботясь о контексте.348349#### `[ast.NodeVisitor]class ast.NodeVisitor`350351Базовый класс для обхода абстрактного синтаксического дерева, который вызывает функцию посетителя для каждого найденного узла. Эта функция может возвращать значение, которое передаётся методом [`visit()`](https://python-all.ru/3.0/library/ast.html#ast.NodeVisitor.visit).352353Этот класс предназначен для наследования; в подклассе добавляются методы-посетители.354355#### `[ast.NodeVisitor.visit]visit(node)`356357Посещает узел. Реализация по умолчанию вызывает метод358359`self.visit_classname`360361, где362363*classname*364365– это имя класса узла, или366367[`generic_visit()`](https://python-all.ru/3.0/library/ast.html#ast.NodeVisitor.generic_visit)368369, если такой метод не существует.370371#### `[ast.NodeVisitor.generic_visit]generic_visit(node)`372373Этот обходчик вызывает [`visit()`](https://python-all.ru/3.0/library/ast.html#ast.NodeVisitor.visit) для всех дочерних узлов данного узла.374375Обратите внимание, что дочерние узлы узлов, для которых определён пользовательский метод обхода, не будут посещены, если обходчик не вызовет [`generic_visit()`](https://python-all.ru/3.0/library/ast.html#ast.NodeVisitor.generic_visit) или не посетит их самостоятельно.376377Не используйте [`NodeVisitor`](https://python-all.ru/3.0/library/ast.html#ast.NodeVisitor) для внесения изменений в узлы во время обхода. Для этого существует специальный обходчик ([`NodeTransformer`](https://python-all.ru/3.0/library/ast.html#ast.NodeTransformer)), позволяющий вносить изменения.378379#### `[ast.NodeTransformer]class ast.NodeTransformer`380381Подкласс [`NodeVisitor`](https://python-all.ru/3.0/library/ast.html#ast.NodeVisitor), который обходит абстрактное синтаксическое дерево и позволяет изменять узлы.382383[`NodeTransformer`](https://python-all.ru/3.0/library/ast.html#ast.NodeTransformer) обходит AST и использует возвращаемое значение методов обхода для замены или удаления старого узла. Если возвращаемое значение метода обхода равно `None`, узел удаляется из своего местоположения; в противном случае он заменяется возвращаемым значением. Возвращаемое значение может быть исходным узлом, и в этом случае замена не производится.384385Вот пример преобразователя, который заменяет все обращения к имени (`foo`) на `data['foo']`:386387```python388class RewriteName(NodeTransformer):389390    def visit_Name(self, node):391        return copy_location(Subscript(392            value=Name(id='data', ctx=Load()),393            slice=Index(value=Str(s=node.id)),394            ctx=node.ctx395        ), node)396```397398Имейте в виду, что если у узла, с которым вы работаете, есть дочерние узлы, вы должны либо преобразовать дочерние узлы самостоятельно, либо сначала вызвать метод `generic_visit()` для этого узла.399400Для узлов, входящих в состав набора инструкций (это относится ко всем узлам инструкций), посетитель может также возвращать список узлов, а не один узел.401402Обычно преобразователь используется следующим образом:403404```python405node = YourTransformer().visit(node)406```407408#### `[ast.dump]ast.dump(node, annotate_fields=True, include_attributes=False)`409410Возвращает форматированное представление дерева в виде дампа из объекта411412*node*413414. Это в основном полезно для целей отладки. Возвращаемая строка покажет имена и значения полей. Это делает код невозможным для выполнения, поэтому если требуется выполнимость,415416*annotate\_fields*417418должен быть установлен в False. Атрибуты, такие как номера строк и смещения столбцов, по умолчанию не выводятся. Если это нужно,419420*include\_attributes*421422можно установить в423424`True`425426.427