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

ast.md

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

1> **Источник:** https://python-all.ru/3.1/library/ast.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 30.2. `ast` – абстрактные синтаксические деревья89Модуль `ast` помогает приложениям Python обрабатывать деревья грамматики абстрактного синтаксиса Python. Сам абстрактный синтаксис может меняться от версии к версии Python; этот модуль позволяет программно узнавать, как выглядит текущая грамматика.1011Абстрактное синтаксическое дерево можно получить, передав `ast.PyCF_ONLY_AST` в качестве флага встроенной функции [`compile()`](https://python-all.ru/3.1/library/functions.html#compile) или воспользовавшись вспомогательной функцией [`parse()`](https://python-all.ru/3.1/library/ast.html#ast.parse), предоставленной в этом модуле. Результатом будет дерево объектов, классы которых наследуют от [`ast.AST`](https://python-all.ru/3.1/library/ast.html#ast.AST). Абстрактное синтаксическое дерево можно скомпилировать в объект кода Python с помощью встроенной функции [`compile()`](https://python-all.ru/3.1/library/functions.html#compile).1213## 30.2.1. Классы узлов1415#### `class ast.AST`1617Это базовый класс для всех узлов AST. Фактические классы узлов порождаются из файла `Parser/Python.asdl`, который воспроизведён [*ниже*](https://python-all.ru/3.1/library/ast.html#abstract-grammar). Они определены в C-модуле `_ast` и повторно экспортируются в `ast`.1819Для каждого символа левой части абстрактной грамматики определён один класс (например, `ast.stmt` или `ast.expr`). Кроме того, для каждого конструктора правой части определён один класс; эти классы наследуют от классов левой части. Например, `ast.BinOp` наследует от `ast.expr`. Для правил вывода с альтернативами (так называемых «сумм») класс левой части является абстрактным: создаются только экземпляры конкретных конструкторных узлов.2021#### `_fields`2223Каждый конкретный класс имеет атрибут [`_fields`](https://python-all.ru/3.1/library/ast.html#ast.AST._fields), который содержит имена всех дочерних узлов.2425Каждый экземпляр конкретного класса имеет по одному атрибуту для каждого дочернего узла, тип которого определён грамматикой. Например, экземпляры `ast.BinOp` имеют атрибут `left` типа `ast.expr`.2627Если эти атрибуты помечены как необязательные в грамматике (с помощью вопросительного знака), их значением может быть `None`. Если атрибуты могут иметь ноль или более значений (помечены звёздочкой), значения представляются в виде списков Python. Все возможные атрибуты должны присутствовать и иметь допустимые значения при компиляции AST с помощью [`compile()`](https://python-all.ru/3.1/library/functions.html#compile).2829#### `lineno`3031#### `col_offset`3233Экземпляры подклассов3435`ast.expr`3637и3839`ast.stmt`4041имеют атрибуты4243[`lineno`](https://python-all.ru/3.1/library/ast.html#ast.AST.lineno)4445и4647[`col_offset`](https://python-all.ru/3.1/library/ast.html#ast.AST.col_offset)4849.5051[`lineno`](https://python-all.ru/3.1/library/ast.html#ast.AST.lineno)5253– это номер строки исходного текста (нумерация с 1, так что первая строка – строка 1), а5455[`col_offset`](https://python-all.ru/3.1/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## 30.2.2. Абстрактная грамматика8586Модуль определяет строковую константу `__version__`, которая содержит десятичный номер ревизии Subversion файла, показанного ниже.8788Абстрактная грамматика в настоящее время определяется следующим образом:8990```python91-- ASDL's four builtin types are identifier, int, string, object9293module Python version "$Revision$"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## 30.2.3. `ast` Вспомогательные функции212213Помимо классов узлов, модуль `ast` определяет следующие вспомогательные функции и классы для обхода абстрактных синтаксических деревьев:214215#### `ast.parse(source, filename='<unknown>', mode='exec')`216217Разбирает исходный код в узел AST. Эквивалентно218219`compile(source, filename, mode, ast.PyCF_ONLY_AST)`220221.222223#### `ast.literal_eval(node_or_string)`224225Безопасно вычисляет узел выражения или строку, содержащую выражение Python. Предоставленная строка или узел может содержать только следующие литеральные структуры Python: строки, числа, кортежи, списки, словари, логические значения и `None`.226227Это можно использовать для безопасного вычисления строк, содержащих выражения Python из ненадёжных источников, без необходимости самостоятельно их разбирать.228229#### `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.1/library/inspect.html#inspect.cleandoc)258259.260261#### `ast.fix_missing_locations(node)`262263При компиляции дерева узлов с помощью264265[`compile()`](https://python-all.ru/3.1/library/functions.html#compile)266267компилятор ожидает атрибуты268269`lineno`270271и272273`col_offset`274275для каждого узла, который их поддерживает. Заполнять их вручную для сгенерированных узлов довольно утомительно, поэтому эта вспомогательная функция рекурсивно добавляет эти атрибуты, если они ещё не установлены, присваивая им значения родительского узла. Она работает рекурсивно, начиная с276277*node*278279.280281#### `ast.increment_lineno(node, n=1)`282283Увеличить номер строки каждого узла в дереве, начиная с284285*node*286287, на288289*n*290291. Это полезно для «переноса кода» в другое место в файле.292293#### `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(node)`318319Генерирует кортеж320321`(fieldname, value)`322323для каждого поля из324325`node._fields`326327, которое присутствует в328329*node*330331.332333#### `ast.iter_child_nodes(node)`334335Генерирует все непосредственные дочерние узлы336337*node*338339, то есть все поля, являющиеся узлами, и все элементы полей, являющихся списками узлов.340341#### `ast.walk(node)`342343Рекурсивно генерирует все узлы-потомки в дереве, начиная с344345*node*346347(включая сам348349*node*350351), в произвольном порядке. Это полезно, если требуется только изменить узлы на месте, а контекст не важен.352353#### `class ast.NodeVisitor`354355Базовый класс для обхода абстрактного синтаксического дерева, который вызывает функцию посетителя для каждого найденного узла. Эта функция может возвращать значение, которое передаётся методом [`visit()`](https://python-all.ru/3.1/library/ast.html#ast.NodeVisitor.visit).356357Этот класс предназначен для наследования; в подклассе добавляются методы-посетители.358359#### `visit(node)`360361Посещает узел. Реализация по умолчанию вызывает метод362363`self.visit_classname`364365, где366367*classname*368369– это имя класса узла, или370371[`generic_visit()`](https://python-all.ru/3.1/library/ast.html#ast.NodeVisitor.generic_visit)372373, если такой метод не существует.374375#### `generic_visit(node)`376377Этот обходчик вызывает [`visit()`](https://python-all.ru/3.1/library/ast.html#ast.NodeVisitor.visit) для всех дочерних узлов данного узла.378379Обратите внимание, что дочерние узлы узлов, для которых определён пользовательский метод обхода, не будут посещены, если обходчик не вызовет [`generic_visit()`](https://python-all.ru/3.1/library/ast.html#ast.NodeVisitor.generic_visit) или не посетит их самостоятельно.380381Не используйте [`NodeVisitor`](https://python-all.ru/3.1/library/ast.html#ast.NodeVisitor) для внесения изменений в узлы во время обхода. Для этого существует специальный обходчик ([`NodeTransformer`](https://python-all.ru/3.1/library/ast.html#ast.NodeTransformer)), позволяющий вносить изменения.382383#### `class ast.NodeTransformer`384385Подкласс [`NodeVisitor`](https://python-all.ru/3.1/library/ast.html#ast.NodeVisitor), который обходит абстрактное синтаксическое дерево и позволяет изменять узлы.386387[`NodeTransformer`](https://python-all.ru/3.1/library/ast.html#ast.NodeTransformer) обходит AST и использует возвращаемое значение методов обхода для замены или удаления старого узла. Если возвращаемое значение метода обхода равно `None`, узел удаляется из своего местоположения; в противном случае он заменяется возвращаемым значением. Возвращаемое значение может быть исходным узлом, и в этом случае замена не производится.388389Вот пример преобразователя, который заменяет все обращения к имени (`foo`) на `data['foo']`:390391```python392class RewriteName(NodeTransformer):393394    def visit_Name(self, node):395        return copy_location(Subscript(396            value=Name(id='data', ctx=Load()),397            slice=Index(value=Str(s=node.id)),398            ctx=node.ctx399        ), node)400```401402Имейте в виду, что если у узла, с которым вы работаете, есть дочерние узлы, вы должны либо преобразовать дочерние узлы самостоятельно, либо сначала вызвать метод `generic_visit()` для этого узла.403404Для узлов, входящих в состав набора инструкций (это относится ко всем узлам инструкций), посетитель может также возвращать список узлов, а не один узел.405406Обычно преобразователь используется следующим образом:407408```python409node = YourTransformer().visit(node)410```411412#### `ast.dump(node, annotate_fields=True, include_attributes=False)`413414Возвращает форматированное представление дерева в виде дампа из объекта415416*node*417418. Это в основном полезно для целей отладки. Возвращаемая строка покажет имена и значения полей. Это делает код невозможным для выполнения, поэтому если требуется выполнимость,419420*annotate\_fields*421422должен быть установлен в False. Атрибуты, такие как номера строк и смещения столбцов, по умолчанию не выводятся. Если это нужно,423424*include\_attributes*425426можно установить в427428`True`429430.431