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

ast.md

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

1> **Источник:** https://python-all.ru/2.6/library/ast.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 31.2. Абстрактные синтаксические деревья89Новое в версии 2.5: Низкоуровневый модуль `_ast`, содержащий только классы узлов.1011Новое в версии 2.6: Высокоуровневый модуль `ast`, содержащий все вспомогательные функции.1213Модуль `ast` помогает приложениям Python обрабатывать деревья грамматики абстрактного синтаксиса Python. Сам абстрактный синтаксис может меняться от версии к версии Python; этот модуль позволяет программно узнавать, как выглядит текущая грамматика.1415Абстрактное синтаксическое дерево можно получить, передав `ast.PyCF_ONLY_AST` в качестве флага встроенной функции [`compile()`](https://python-all.ru/2.6/library/functions.html#compile) или воспользовавшись вспомогательной функцией [`parse()`](https://python-all.ru/2.6/library/ast.html#ast.parse), предоставленной в этом модуле. Результатом будет дерево объектов, классы которых наследуют от [`ast.AST`](https://python-all.ru/2.6/library/ast.html#ast.AST). Абстрактное синтаксическое дерево можно скомпилировать в объект кода Python с помощью встроенной функции [`compile()`](https://python-all.ru/2.6/library/functions.html#compile).1617## 31.2.1. Классы узлов1819#### `class ast.AST`2021Это базовый класс для всех узлов AST. Фактические классы узлов порождаются из файла `Parser/Python.asdl`, который воспроизведён [*ниже*](https://python-all.ru/2.6/library/ast.html#abstract-grammar). Они определены в C-модуле `_ast` и повторно экспортируются в `ast`.2223Для каждого символа левой части абстрактной грамматики определён один класс (например, `ast.stmt` или `ast.expr`). Кроме того, для каждого конструктора правой части определён один класс; эти классы наследуют от классов левой части. Например, `ast.BinOp` наследует от `ast.expr`. Для правил вывода с альтернативами (так называемых «сумм») класс левой части является абстрактным: создаются только экземпляры конкретных конструкторных узлов.2425#### `_fields`2627Каждый конкретный класс имеет атрибут [`_fields`](https://python-all.ru/2.6/library/ast.html#ast.AST._fields), который содержит имена всех дочерних узлов.2829Каждый экземпляр конкретного класса имеет по одному атрибуту для каждого дочернего узла, тип которого определён грамматикой. Например, экземпляры `ast.BinOp` имеют атрибут `left` типа `ast.expr`.3031Если эти атрибуты помечены как необязательные в грамматике (с помощью вопросительного знака), их значением может быть `None`. Если атрибуты могут иметь ноль или более значений (помечены звёздочкой), значения представляются в виде списков Python. Все возможные атрибуты должны присутствовать и иметь допустимые значения при компиляции AST с помощью [`compile()`](https://python-all.ru/2.6/library/functions.html#compile).3233#### `lineno`3435#### `col_offset`3637Экземпляры подклассов3839`ast.expr`4041и4243`ast.stmt`4445имеют атрибуты4647[`lineno`](https://python-all.ru/2.6/library/ast.html#ast.AST.lineno)4849и5051[`col_offset`](https://python-all.ru/2.6/library/ast.html#ast.AST.col_offset)5253.5455[`lineno`](https://python-all.ru/2.6/library/ast.html#ast.AST.lineno)5657– это номер строки исходного текста (нумерация с 1, так что первая строка – строка 1), а5859[`col_offset`](https://python-all.ru/2.6/library/ast.html#ast.AST.col_offset)6061– это смещение в байтах UTF-8 первого токена, породившего узел. Смещение в UTF-8 записывается, потому что парсер использует UTF-8 внутри.6263Конструктор класса `ast.T` разбирает свои аргументы следующим образом:6465- Если есть позиционные аргументы, их должно быть столько же, сколько элементов в `T._fields`; они будут присвоены как атрибуты с этими именами.66- Если есть ключевые аргументы, они установят атрибуты с теми же именами в указанные значения.6768Например, чтобы создать и заполнить узел `ast.UnaryOp`, можно использовать6970```python71node = ast.UnaryOp()72node.op = ast.USub()73node.operand = ast.Num()74node.operand.n = 575node.operand.lineno = 076node.operand.col_offset = 077node.lineno = 078node.col_offset = 079```8081или более компактный8283```python84node = ast.UnaryOp(ast.USub(), ast.Num(5, lineno=0, col_offset=0),85                   lineno=0, col_offset=0)86```8788Новое в версии 2.6: Конструктор, описанный выше, был добавлен. В Python 2.5 узлы должны были создаваться вызовом конструктора класса без аргументов и последующей установкой атрибутов.8990## 31.2.2. Абстрактная грамматика9192Модуль определяет строковую константу `__version__`, которая содержит десятичный номер ревизии Subversion файла, показанного ниже.9394Абстрактная грамматика в настоящее время определяется следующим образом:9596```python97-- ASDL's five builtin types are identifier, int, string, object, bool9899module Python version "$Revision$"100{101	mod = Module(stmt* body)102	    | Interactive(stmt* body)103	    | Expression(expr body)104105	    -- not really an actual node but useful in Jython's typesystem.106	    | Suite(stmt* body)107108	stmt = FunctionDef(identifier name, arguments args, 109                            stmt* body, expr* decorator_list)110	      | ClassDef(identifier name, expr* bases, stmt* body, 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	      -- not sure if bool is allowed, can always use int118 	      | Print(expr? dest, expr* values, bool nl)119120	      -- use 'orelse' because else is a keyword in target languages121	      | For(expr target, expr iter, stmt* body, stmt* orelse)122	      | While(expr test, stmt* body, stmt* orelse)123	      | If(expr test, stmt* body, stmt* orelse)124	      | With(expr context_expr, expr? optional_vars, stmt* body)125126	      -- 'type' is a bad name127	      | Raise(expr? type, expr? inst, expr? tback)128	      | TryExcept(stmt* body, excepthandler* handlers, stmt* orelse)129	      | TryFinally(stmt* body, stmt* finalbody)130	      | Assert(expr test, expr? msg)131132	      | Import(alias* names)133	      | ImportFrom(identifier module, alias* names, int? level)134135	      -- Doesn't capture requirement that locals must be136	      -- defined if globals is137	      -- still supports use as a function!138	      | Exec(expr body, expr? globals, expr? locals)139140	      | Global(identifier* names)141	      | Expr(expr value)142	      | Pass | Break | Continue143144	      -- XXX Jython will be different145	      -- col_offset is the byte offset in the utf8 string the parser uses146	      attributes (int lineno, int col_offset)147148	      -- BoolOp() can use left & right?149	expr = BoolOp(boolop op, expr* values)150	     | BinOp(expr left, operator op, expr right)151	     | UnaryOp(unaryop op, expr operand)152	     | Lambda(arguments args, expr body)153	     | IfExp(expr test, expr body, expr orelse)154	     | Dict(expr* keys, expr* values)155	     | ListComp(expr elt, comprehension* generators)156	     | GeneratorExp(expr elt, comprehension* generators)157	     -- the grammar constrains where yield expressions can occur158	     | Yield(expr? value)159	     -- need sequences for compare to distinguish between160	     -- x < 4 < 3 and (x < 4) < 3161	     | Compare(expr left, cmpop* ops, expr* comparators)162	     | Call(expr func, expr* args, keyword* keywords,163			 expr? starargs, expr? kwargs)164	     | Repr(expr value)165	     | Num(object n) -- a number as a PyObject.166	     | Str(string s) -- need to specify raw, unicode, etc?167	     -- other literals? bools?168169	     -- the following expression can appear in assignment context170	     | Attribute(expr value, identifier attr, expr_context ctx)171	     | Subscript(expr value, slice slice, expr_context ctx)172	     | Name(identifier id, expr_context ctx)173	     | List(expr* elts, expr_context ctx) 174	     | Tuple(expr* elts, expr_context ctx)175176	      -- col_offset is the byte offset in the utf8 string the parser uses177	      attributes (int lineno, int col_offset)178179	expr_context = Load | Store | Del | AugLoad | AugStore | Param180181	slice = Ellipsis | Slice(expr? lower, expr? upper, expr? step) 182	      | ExtSlice(slice* dims) 183	      | Index(expr value) 184185	boolop = And | Or 186187	operator = Add | Sub | Mult | Div | Mod | Pow | LShift 188                 | RShift | BitOr | BitXor | BitAnd | FloorDiv189190	unaryop = Invert | Not | UAdd | USub191192	cmpop = Eq | NotEq | Lt | LtE | Gt | GtE | Is | IsNot | In | NotIn193194	comprehension = (expr target, expr iter, expr* ifs)195196	-- not sure what to call the first argument for raise and except197	excepthandler = ExceptHandler(expr? type, expr? name, stmt* body)198	                attributes (int lineno, int col_offset)199200	arguments = (expr* args, identifier? vararg, 201		     identifier? kwarg, expr* defaults)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## 31.2.3. `ast` Вспомогательные функции212213Новое в версии 2.6.214215Помимо классов узлов, модуль `ast` определяет следующие вспомогательные функции и классы для обхода абстрактных синтаксических деревьев:216217#### `ast.parse(expr, filename='<unknown>', mode='exec')`218219Разбирает выражение в узел AST. Эквивалентно220221`compile(expr, filename, mode, ast.PyCF_ONLY_AST)`222223.224225#### `ast.literal_eval(node_or_string)`226227Безопасно вычисляет узел выражения или строку, содержащую выражение Python. Предоставленная строка или узел может содержать только следующие литеральные структуры Python: строки, числа, кортежи, списки, словари, логические значения и `None`.228229Это можно использовать для безопасного вычисления строк, содержащих выражения Python из ненадёжных источников, без необходимости самостоятельно их разбирать.230231#### `ast.get_docstring(node, clean=True)`232233Возвращает docstring заданного234235*node*236237(который должен быть узлом238239`FunctionDef`240241,242243`ClassDef`244245или246247`Module`248249), или250251`None`252253, если docstring нет. Если254255*clean*256257равно True, очищает отступы docstring с помощью258259[`inspect.cleandoc()`](https://python-all.ru/2.6/library/inspect.html#inspect.cleandoc)260261.262263#### `ast.fix_missing_locations(node)`264265При компиляции дерева узлов с помощью266267[`compile()`](https://python-all.ru/2.6/library/functions.html#compile)268269компилятор ожидает атрибуты270271`lineno`272273и274275`col_offset`276277для каждого узла, который их поддерживает. Заполнять их вручную для сгенерированных узлов довольно утомительно, поэтому эта вспомогательная функция рекурсивно добавляет эти атрибуты, если они ещё не установлены, присваивая им значения родительского узла. Она работает рекурсивно, начиная с278279*node*280281.282283#### `ast.increment_lineno(node, n=1)`284285Увеличить номер строки каждого узла в дереве, начиная с286287*node*288289, на290291*n*292293. Это полезно для «переноса кода» в другое место в файле.294295#### `ast.copy_location(new_node, old_node)`296297Копирует информацию о положении в исходном коде (298299`lineno`300301и302303`col_offset`304305) из306307*old\_node*308309в310311*new\_node*312313, если это возможно, и возвращает314315*new\_node*316317.318319#### `ast.iter_fields(node)`320321Генерирует кортеж322323`(fieldname, value)`324325для каждого поля из326327`node._fields`328329, которое присутствует в330331*node*332333.334335#### `ast.iter_child_nodes(node)`336337Генерирует все непосредственные дочерние узлы338339*node*340341, то есть все поля, являющиеся узлами, и все элементы полей, являющихся списками узлов.342343#### `ast.walk(node)`344345Рекурсивно выдаёт все дочерние узлы346347*node*348349в произвольном порядке. Это полезно, если требуется только изменить узлы на месте, не заботясь о контексте.350351#### `class ast.NodeVisitor`352353Базовый класс для обхода абстрактного синтаксического дерева, который вызывает функцию посетителя для каждого найденного узла. Эта функция может возвращать значение, которое передаётся методом [`visit()`](https://python-all.ru/2.6/library/ast.html#ast.NodeVisitor.visit).354355Этот класс предназначен для наследования; в подклассе добавляются методы-посетители.356357#### `visit(node)`358359Посещает узел. Реализация по умолчанию вызывает метод360361`self.visit_classname`362363, где364365*classname*366367– это имя класса узла, или368369[`generic_visit()`](https://python-all.ru/2.6/library/ast.html#ast.NodeVisitor.generic_visit)370371, если такой метод не существует.372373#### `generic_visit(node)`374375Этот обходчик вызывает [`visit()`](https://python-all.ru/2.6/library/ast.html#ast.NodeVisitor.visit) для всех дочерних узлов данного узла.376377Обратите внимание, что дочерние узлы узлов, для которых определён пользовательский метод обхода, не будут посещены, если обходчик не вызовет [`generic_visit()`](https://python-all.ru/2.6/library/ast.html#ast.NodeVisitor.generic_visit) или не посетит их самостоятельно.378379Не используйте [`NodeVisitor`](https://python-all.ru/2.6/library/ast.html#ast.NodeVisitor) для внесения изменений в узлы во время обхода. Для этого существует специальный обходчик ([`NodeTransformer`](https://python-all.ru/2.6/library/ast.html#ast.NodeTransformer)), позволяющий вносить изменения.380381#### `class ast.NodeTransformer`382383Подкласс [`NodeVisitor`](https://python-all.ru/2.6/library/ast.html#ast.NodeVisitor), который обходит абстрактное синтаксическое дерево и позволяет изменять узлы.384385[`NodeTransformer`](https://python-all.ru/2.6/library/ast.html#ast.NodeTransformer) обходит AST и использует возвращаемое значение методов обхода для замены или удаления старого узла. Если возвращаемое значение метода обхода равно `None`, узел удаляется из своего местоположения; в противном случае он заменяется возвращаемым значением. Возвращаемое значение может быть исходным узлом, и в этом случае замена не производится.386387Вот пример преобразователя, который заменяет все обращения к имени (`foo`) на `data['foo']`:388389```python390class RewriteName(NodeTransformer):391392    def visit_Name(self, node):393        return copy_location(Subscript(394            value=Name(id='data', ctx=Load()),395            slice=Index(value=Str(s=node.id)),396            ctx=node.ctx397        ), node)398```399400Имейте в виду, что если у узла, с которым вы работаете, есть дочерние узлы, вы должны либо преобразовать дочерние узлы самостоятельно, либо сначала вызвать метод `generic_visit()` для этого узла.401402Для узлов, входящих в состав набора инструкций (это относится ко всем узлам инструкций), посетитель может также возвращать список узлов, а не один узел.403404Обычно преобразователь используется следующим образом:405406```python407node = YourTransformer().visit(node)408```409410#### `ast.dump(node, annotate_fields=True, include_attributes=False)`411412Возвращает форматированное представление дерева в виде дампа из объекта413414*node*415416. Это в основном полезно для целей отладки. Возвращаемая строка покажет имена и значения полей. Это делает код невозможным для выполнения, поэтому если требуется выполнимость,417418*annotate\_fields*419420должен быть установлен в False. Атрибуты, такие как номера строк и смещения столбцов, по умолчанию не выводятся. Если это нужно,421422*include\_attributes*423424можно установить в425426`True`427428.429