Spec-Zone.ru › Python 3.9

ast — Деревья абстрактной синтаксической структуры

Исходный код: Lib/ast.py

Модуль ast помогает приложениям Python обрабатывать деревья абстрактной синтаксической грамматики Python. Сама абстрактная синтаксическая структура может изменяться с каждым выпуском Python; этот модуль помогает программно определить, какой вид грамматики используется в текущей версии.

Дерево абстрактной синтаксической структуры можно сгенерировать, передав ast.PyCF_ONLY_AST в качестве флага функции compile() или используя вспомогательную функцию parse() из этого модуля. Результатом будет дерево объектов, классы которых наследуются от ast.AST. Дерево абстрактной синтаксической структуры можно скомпилировать в объект кода Python с помощью встроенной функции compile().

Абстрактная грамматика

В настоящее время абстрактная грамматика определена следующим образом:

-- ASDL's 4 builtin types are:
-- identifier, int, string, constant

module Python
{
    mod = Module(stmt* body, type_ignore* type_ignores)
        | Interactive(stmt* body)
        | Expression(expr body)
        | FunctionType(expr* argtypes, expr returns)

    stmt = FunctionDef(identifier name, arguments args,
                       stmt* body, expr* decorator_list, expr? returns,
                       string? type_comment)
          | AsyncFunctionDef(identifier name, arguments args,
                             stmt* body, expr* decorator_list, expr? returns,
                             string? type_comment)

          | ClassDef(identifier name,
             expr* bases,
             keyword* keywords,
             stmt* body,
             expr* decorator_list)
          | Return(expr? value)

          | Delete(expr* targets)
          | Assign(expr* targets, expr value, string? type_comment)
          | AugAssign(expr target, operator op, expr value)
          -- 'simple' indicates that we annotate simple name without parens
          | AnnAssign(expr target, expr annotation, expr? value, int simple)

          -- use 'orelse' because else is a keyword in target languages
          | For(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment)
          | AsyncFor(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment)
          | While(expr test, stmt* body, stmt* orelse)
          | If(expr test, stmt* body, stmt* orelse)
          | With(withitem* items, stmt* body, string? type_comment)
          | AsyncWith(withitem* items, stmt* body, string? type_comment)

          | Raise(expr? exc, expr? cause)
          | Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)
          | Assert(expr test, expr? msg)

          | Import(alias* names)
          | ImportFrom(identifier? module, alias* names, int? level)

          | Global(identifier* names)
          | Nonlocal(identifier* names)
          | Expr(expr value)
          | Pass | Break | Continue

          -- col_offset is the byte offset in the utf8 string the parser uses
          attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)

          -- BoolOp() can use left & right?
    expr = BoolOp(boolop op, expr* values)
         | NamedExpr(expr target, expr value)
         | BinOp(expr left, operator op, expr right)
         | UnaryOp(unaryop op, expr operand)
         | Lambda(arguments args, expr body)
         | IfExp(expr test, expr body, expr orelse)
         | Dict(expr* keys, expr* values)
         | Set(expr* elts)
         | ListComp(expr elt, comprehension* generators)
         | SetComp(expr elt, comprehension* generators)
         | DictComp(expr key, expr value, comprehension* generators)
         | GeneratorExp(expr elt, comprehension* generators)
         -- the grammar constrains where yield expressions can occur
         | Await(expr value)
         | Yield(expr? value)
         | YieldFrom(expr value)
         -- need sequences for compare to distinguish between
         -- x < 4 < 3 and (x < 4) < 3
         | Compare(expr left, cmpop* ops, expr* comparators)
         | Call(expr func, expr* args, keyword* keywords)
         | FormattedValue(expr value, int? conversion, expr? format_spec)
         | JoinedStr(expr* values)
         | Constant(constant value, string? kind)

         -- the following expression can appear in assignment context
         | Attribute(expr value, identifier attr, expr_context ctx)
         | Subscript(expr value, expr slice, expr_context ctx)
         | Starred(expr value, expr_context ctx)
         | Name(identifier id, expr_context ctx)
         | List(expr* elts, expr_context ctx)
         | Tuple(expr* elts, expr_context ctx)

         -- can appear only in Subscript
         | Slice(expr? lower, expr? upper, expr? step)

          -- col_offset is the byte offset in the utf8 string the parser uses
          attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)

    expr_context = Load | Store | Del

    boolop = And | Or

    operator = Add | Sub | Mult | MatMult | Div | Mod | Pow | LShift
                 | RShift | BitOr | BitXor | BitAnd | FloorDiv

    unaryop = Invert | Not | UAdd | USub

    cmpop = Eq | NotEq | Lt | LtE | Gt | GtE | Is | IsNot | In | NotIn

    comprehension = (expr target, expr iter, expr* ifs, int is_async)

    excepthandler = ExceptHandler(expr? type, identifier? name, stmt* body)
                    attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)

    arguments = (arg* posonlyargs, arg* args, arg? vararg, arg* kwonlyargs,
                 expr* kw_defaults, arg? kwarg, expr* defaults)

    arg = (identifier arg, expr? annotation, string? type_comment)
           attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)

    -- keyword arguments supplied to call (NULL identifier for **kwargs)
    keyword = (identifier? arg, expr value)
               attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)

    -- import name with optional 'as' alias.
    alias = (identifier name, identifier? asname)

    withitem = (expr context_expr, expr? optional_vars)

    type_ignore = TypeIgnore(int lineno, string tag)
}

Классы узлов

class ast.AST

Это базовый класс для всех классов узлов AST. Фактические классы узлов получены из файла Parser/Python.asdl, который воспроизведён ниже. Они определены в модуле C _ast и повторно экспортированы в ast.

Для каждого левостороннего символа в абстрактной грамматике (например, ast.stmt или ast.expr) определён один класс. Кроме того, для каждого конструктора в правой части определён один класс; эти классы наследуются от классов для деревьев левой части. Например, ast.BinOp наследуется от ast.expr. Для правил вывода с альтернативами (также называемых «суммами») класс левой части является абстрактным: создаются только экземпляры конкретных узлов конструкторов.

_fields

Каждый конкретный класс имеет атрибут _fields, который указывает имена всех дочерних узлов.

Каждый экземпляр конкретного класса имеет один атрибут для каждого дочернего узла, типа, определённого в грамматике. Например, экземпляры ast.BinOp имеют атрибут left типа ast.expr.

Если эти атрибуты помечены как необязательные в грамматике (с использованием вопросительного знака), значение может быть None. Если атрибуты могут иметь ноль или более значений (помечены звездочкой), значения представлены в виде списков Python. Все возможные атрибуты должны быть присутствовать и иметь допустимые значения при компиляции AST с помощью compile().

lineno
col_offset
end_lineno
end_col_offset

Экземпляры подклассов ast.expr и ast.stmt имеют атрибуты lineno, col_offset, end_lineno и end_col_offset. lineno и end_lineno — номера первой и последней строк исходного текста (индексированы с 1, так что первая строка — строка 1), а col_offset и end_col_offset — соответствующие смещения байтов UTF-8 первых и последних токенов, породивших узел. Смещение в UTF-8 записывается, потому что парсер использует UTF-8 внутри.

Обратите внимание, что конечные позиции не требуются компилятору и, следовательно, являются необязательными. Конечное смещение находится после последнего символа, например, можно получить фрагмент исходного текста узла однострочного выражения с помощью source_line[node.col_offset : node.end_col_offset].

Конструктор класса ast.T анализирует свои аргументы следующим образом:

  • Если есть позиционные аргументы, их должно быть столько же, сколько элементов в T._fields; они будут назначены как атрибуты с этими именами.
  • Если есть именованные аргументы, они установят атрибуты с теми же именами на заданные значения.

Например, чтобы создать и заполнить узел ast.UnaryOp, можно использовать

node = ast.UnaryOp()
node.op = ast.USub()
node.operand = ast.Constant()
node.operand.value = 5
node.operand.lineno = 0
node.operand.col_offset = 0
node.lineno = 0
node.col_offset = 0

или более компактный вариант

node = ast.UnaryOp(ast.USub(), ast.Constant(5, lineno=0, col_offset=0),
                   lineno=0, col_offset=0)

Изменено в версии 3.8: Класс ast.Constant теперь используется для всех констант.

Изменено в версии 3.9: Простые индексы представлены их значением, расширенные срезы — кортежами.

Устарело начиная с версии 3.8: Старые классы ast.Num, ast.Str, ast.Bytes, ast.NameConstant и ast.Ellipsis по-прежнему доступны, но будут удалены в будущих выпусках Python. Пока что их создание вернёт экземпляр другого класса.

Устарело начиная с версии 3.9: Старые классы ast.Index и ast.ExtSlice по-прежнему доступны, но будут удалены в будущих выпусках Python. Пока что их создание вернёт экземпляр другого класса.

Примечание

Описание конкретных классов узлов, показанных здесь, изначально было адаптировано из замечательного проекта Green Tree Snakes и всех его авторов.

Литералы

class ast.Constant(value)

Константа. Атрибут value литерала Constant содержит представляемый им Python-объект. Представленные значения могут быть простыми типами, такими как число, строка или None, а также неизменяемыми контейнерными типами (кортежи и замороженные множества), если все их элементы являются константами.

>>> print(ast.dump(ast.parse('123', mode='eval'), indent=4))
Expression(
    body=Constant(value=123))
class ast.FormattedValue(value, conversion, format_spec)

Узел, представляющий одно поле форматирования в строке f-строки. Если строка содержит единственное поле форматирования и ничего больше, узел может быть изолирован, в противном случае он появляется в JoinedStr.

  • value — это любой узел выражения (такой как литерал, переменная или вызов функции).
  • conversion — целое число:

    • -1: без форматирования
    • 115: форматирование строки !s
    • 114: форматирование repr !r
    • 97: форматирование ascii !a
  • format_spec — узел JoinedStr, представляющий форматирование значения, или None если форматирование не было указано. Оба conversion и format_spec могут быть установлены одновременно.
class ast.JoinedStr(values)

F-строка, состоящая из ряда узлов FormattedValue и Constant.

>>> print(ast.dump(ast.parse('f"sin({a}) is {sin(a):.3}"', mode='eval'), indent=4))
Expression(
    body=JoinedStr(
        values=[
            Constant(value='sin('),
            FormattedValue(
                value=Name(id='a', ctx=Load()),
                conversion=-1),
            Constant(value=') is '),
            FormattedValue(
                value=Call(
                    func=Name(id='sin', ctx=Load()),
                    args=[
                        Name(id='a', ctx=Load())],
                    keywords=[]),
                conversion=-1,
                format_spec=JoinedStr(
                    values=[
                        Constant(value='.3')]))]))
class ast.List(elts, ctx)
class ast.Tuple(elts, ctx)

Список или кортеж. elts содержит список узлов, представляющих элементы. ctx — Store, если контейнер является целью присваивания (т.е. (x,y)=something), и Load в противном случае.

>>> print(ast.dump(ast.parse('[1, 2, 3]', mode='eval'), indent=4))
Expression(
    body=List(
        elts=[
            Constant(value=1),
            Constant(value=2),
            Constant(value=3)],
        ctx=Load()))
>>> print(ast.dump(ast.parse('(1, 2, 3)', mode='eval'), indent=4))
Expression(
    body=Tuple(
        elts=[
            Constant(value=1),
            Constant(value=2),
            Constant(value=3)],
        ctx=Load()))
class ast.Set(elts)

Множество. elts содержит список узлов, представляющих элементы множества.

>>> print(ast.dump(ast.parse('{1, 2, 3}', mode='eval'), indent=4))
Expression(
    body=Set(
        elts=[
            Constant(value=1),
            Constant(value=2),
            Constant(value=3)]))
class ast.Dict(keys, values)

Словарь. keys и values содержат списки узлов, представляющих ключи и значения соответственно, в соответствующем порядке (что будет возвращено при вызове dictionary.keys() и dictionary.values()).

При распаковке словарей с использованием литералов словарей выражение для распаковки идёт в список values, а None — в соответствующую позицию в keys.

>>> print(ast.dump(ast.parse('{"a":1, **d}', mode='eval'), indent=4))
Expression(
    body=Dict(
        keys=[
            Constant(value='a'),
            None],
        values=[
            Constant(value=1),
            Name(id='d', ctx=Load())]))

Переменные

class ast.Name(id, ctx)

Имя переменной. id содержит имя в виде строки, а ctx — один из следующих типов.

class ast.Load
class ast.Store
class ast.Del

Ссылаясь на переменные, можно получить её значение, присвоить новое значение или удалить её. Ссылка на переменную имеет контекст для различения этих случаев.

>>> print(ast.dump(ast.parse('a'), indent=4))
Module(
    body=[
        Expr(
            value=Name(id='a', ctx=Load()))],
    type_ignores=[])

>>> print(ast.dump(ast.parse('a = 1'), indent=4))
Module(
    body=[
        Assign(
            targets=[
                Name(id='a', ctx=Store())],
            value=Constant(value=1))],
    type_ignores=[])

>>> print(ast.dump(ast.parse('del a'), indent=4))
Module(
    body=[
        Delete(
            targets=[
                Name(id='a', ctx=Del())])],
    type_ignores=[])
class ast.Starred(value, ctx)

Ссылка на переменную с *var. value содержит переменную, обычно узел Name. Этот тип должен использоваться при построении узла Call с *args.

>>> print(ast.dump(ast.parse('a, *b = it'), indent=4))
Module(
    body=[
        Assign(
            targets=[
                Tuple(
                    elts=[
                        Name(id='a', ctx=Store()),
                        Starred(
                            value=Name(id='b', ctx=Store()),
                            ctx=Store())],
                    ctx=Store())],
            value=Name(id='it', ctx=Load()))],
    type_ignores=[])

Выражения

class ast.Expr(value)

Когда выражение, например, вызов функции, используется как оператор само по себе, без использования или сохранения его возвращаемого значения, оно оборачивается в этот контейнер. value содержит один из других узлов в этом разделе, узел Constant, Name, Lambda, Yield или YieldFrom.

>>> print(ast.dump(ast.parse('-a'), indent=4))
Module(
    body=[
        Expr(
            value=UnaryOp(
                op=USub(),
                operand=Name(id='a', ctx=Load())))],
    type_ignores=[])
class ast.UnaryOp(op, operand)

Унарная операция. op - это оператор, а operand - любой узел выражения.

class ast.UAdd
class ast.USub
class ast.Not
class ast.Invert

Токены унарных операторов. Not - это ключевое слово not, Invert - оператор ~.

>>> print(ast.dump(ast.parse('not x', mode='eval'), indent=4))
Expression(
    body=UnaryOp(
        op=Not(),
        operand=Name(id='x', ctx=Load())))
class ast.BinOp(left, op, right)

Бинарная операция (например, сложение или деление). op - это оператор, а left и right - любые узлы выражения.

>>> print(ast.dump(ast.parse('x + y', mode='eval'), indent=4))
Expression(
    body=BinOp(
        left=Name(id='x', ctx=Load()),
        op=Add(),
        right=Name(id='y', ctx=Load())))
class ast.Add
class ast.Sub
class ast.Mult
class ast.Div
class ast.FloorDiv
class ast.Mod
class ast.Pow
class ast.LShift
class ast.RShift
class ast.BitOr
class ast.BitXor
class ast.BitAnd
class ast.MatMult

Токены бинарных операторов.

class ast.BoolOp(op, values)

Булева операция, «или» или «и». op это Or или And. values - это участвующие значения. Последовательные операции с одним и тем же оператором, такие как a or b or c, сводятся к одному узлу с несколькими значениями.

Это не включает not, которое является UnaryOp.

>>> print(ast.dump(ast.parse('x or y', mode='eval'), indent=4))
Expression(
    body=BoolOp(
        op=Or(),
        values=[
            Name(id='x', ctx=Load()),
            Name(id='y', ctx=Load())]))
class ast.And
class ast.Or

Булевы операторные токены.

class ast.Compare(left, ops, comparators)

Сравнение двух или более значений. left - первое значение в сравнении, ops - список операторов, а comparators - список значений после первого элемента в сравнении.

>>> print(ast.dump(ast.parse('1 <= a < 10', mode='eval'), indent=4))
Expression(
    body=Compare(
        left=Constant(value=1),
        ops=[
            LtE(),
            Lt()],
        comparators=[
            Name(id='a', ctx=Load()),
            Constant(value=10)]))
class ast.Eq
class ast.NotEq
class ast.Lt
class ast.LtE
class ast.Gt
class ast.GtE
class ast.Is
class ast.IsNot
class ast.In
class ast.NotIn

Токены операторов сравнения.

class ast.Call(func, args, keywords, starargs, kwargs)

Вызов функции. func - это функция, которая часто будет объектом Name или Attribute. Из аргументов:

  • args содержит список аргументов, передаваемых по позиции.
  • keywords содержит список объектов keyword, представляющих аргументы, передаваемые по имени.

При создании узла Call, args и keywords являются обязательными, но они могут быть пустыми списками. starargs и kwargs являются необязательными.

>>> print(ast.dump(ast.parse('func(a, b=c, *d, **e)', mode='eval'), indent=4))
Expression(
    body=Call(
        func=Name(id='func', ctx=Load()),
        args=[
            Name(id='a', ctx=Load()),
            Starred(
                value=Name(id='d', ctx=Load()),
                ctx=Load())],
        keywords=[
            keyword(
                arg='b',
                value=Name(id='c', ctx=Load())),
            keyword(
                value=Name(id='e', ctx=Load()))]))
class ast.keyword(arg, value)

Аргумент ключевого слова для вызова функции или определения класса. arg - это строка имени параметра, value - это узел для передачи.

class ast.IfExp(test, body, orelse)

Выражение, например, a if b else c. Каждый поле содержит один узел, поэтому в следующем примере все три являются узлами Name.

>>> print(ast.dump(ast.parse('a if b else c', mode='eval'), indent=4))
Expression(
    body=IfExp(
        test=Name(id='b', ctx=Load()),
        body=Name(id='a', ctx=Load()),
        orelse=Name(id='c', ctx=Load())))
class ast.Attribute(value, attr, ctx)

Обращение к атрибуту, например, d.keys. value - это узел, как правило, Name. attr - это обычная строка, содержащая имя атрибута, а ctx - Load, Store или Del в зависимости от того, как происходит обращение к атрибуту.

>>> print(ast.dump(ast.parse('snake.colour', mode='eval'), indent=4))
Expression(
    body=Attribute(
        value=Name(id='snake', ctx=Load()),
        attr='colour',
        ctx=Load()))
class ast.NamedExpr(target, value)

Именованное выражение. Этот узел AST создается оператором выражений присваивания (также известным как оператор walrus). В отличие от узла Assign, в котором первый аргумент может содержать несколько узлов, в данном случае и target и value должны быть одиночными узлами.

>>> print(ast.dump(ast.parse('(x := 4)', mode='eval'), indent=4))
Expression(
    body=NamedExpr(
        target=Name(id='x', ctx=Store()),
        value=Constant(value=4)))

Индексирование

class ast.Subscript(value, slice, ctx)

Индексирование, например, l[1]. value - это индексируемый объект (обычно последовательность или отображение). slice - индекс, срез или ключ. Он может быть Tuple и содержать Slice. ctx - это Load, Store или Del в зависимости от выполняемого действия.

>>> print(ast.dump(ast.parse('l[1:2, 3]', mode='eval'), indent=4))
Expression(
    body=Subscript(
        value=Name(id='l', ctx=Load()),
        slice=Tuple(
            elts=[
                Slice(
                    lower=Constant(value=1),
                    upper=Constant(value=2)),
                Constant(value=3)],
            ctx=Load()),
        ctx=Load()))
class ast.Slice(lower, upper, step)

Обычный срез (в формате lower:upper или lower:upper:step). Может встречаться только в поле slice узла Subscript, либо непосредственно, либо как элемент Tuple.

>>> print(ast.dump(ast.parse('l[1:2]', mode='eval'), indent=4))
Expression(
    body=Subscript(
        value=Name(id='l', ctx=Load()),
        slice=Slice(
            lower=Constant(value=1),
            upper=Constant(value=2)),
        ctx=Load()))

Списки с выражениями

class ast.ListComp(elt, generators)
class ast.SetComp(elt, generators)
class ast.GeneratorExp(elt, generators)
class ast.DictComp(key, value, generators)

Списки и множества с выражениями, генераторные выражения и словари с выражениями. elt (или key и value ) - это единственный узел, представляющий часть, которая будет вычисляться для каждого элемента.

generators - это список узлов comprehension.

>>> print(ast.dump(ast.parse('[x for x in numbers]', mode='eval'), indent=4))
Expression(
    body=ListComp(
        elt=Name(id='x', ctx=Load()),
        generators=[
            comprehension(
                target=Name(id='x', ctx=Store()),
                iter=Name(id='numbers', ctx=Load()),
                ifs=[],
                is_async=0)]))
>>> print(ast.dump(ast.parse('{x: x**2 for x in numbers}', mode='eval'), indent=4))
Expression(
    body=DictComp(
        key=Name(id='x', ctx=Load()),
        value=BinOp(
            left=Name(id='x', ctx=Load()),
            op=Pow(),
            right=Constant(value=2)),
        generators=[
            comprehension(
                target=Name(id='x', ctx=Store()),
                iter=Name(id='numbers', ctx=Load()),
                ifs=[],
                is_async=0)]))
>>> print(ast.dump(ast.parse('{x for x in numbers}', mode='eval'), indent=4))
Expression(
    body=SetComp(
        elt=Name(id='x', ctx=Load()),
        generators=[
            comprehension(
                target=Name(id='x', ctx=Store()),
                iter=Name(id='numbers', ctx=Load()),
                ifs=[],
                is_async=0)]))
class ast.comprehension(target, iter, ifs, is_async)

Один for блок в списке с выражениями. target - ссылка для использования каждого элемента, обычно узел Name или Tuple. iter - это объект для итерирования. ifs - это список тестовых выражений: каждый for блок может иметь несколько ifs.

is_async указывает, является ли список с выражениями асинхронным (используя async for вместо for). Значение - целое число (0 или 1).

>>> print(ast.dump(ast.parse('[ord(c) for line in file for c in line]', mode='eval'),
...                indent=4)) # Multiple comprehensions in one.
Expression(
    body=ListComp(
        elt=Call(
            func=Name(id='ord', ctx=Load()),
            args=[
                Name(id='c', ctx=Load())],
            keywords=[]),
        generators=[
            comprehension(
                target=Name(id='line', ctx=Store()),
                iter=Name(id='file', ctx=Load()),
                ifs=[],
                is_async=0),
            comprehension(
                target=Name(id='c', ctx=Store()),
                iter=Name(id='line', ctx=Load()),
                ifs=[],
                is_async=0)]))

>>> print(ast.dump(ast.parse('(n**2 for n in it if n>5 if n<10)', mode='eval'),
...                indent=4)) # generator comprehension
Expression(
    body=GeneratorExp(
        elt=BinOp(
            left=Name(id='n', ctx=Load()),
            op=Pow(),
            right=Constant(value=2)),
        generators=[
            comprehension(
                target=Name(id='n', ctx=Store()),
                iter=Name(id='it', ctx=Load()),
                ifs=[
                    Compare(
                        left=Name(id='n', ctx=Load()),
                        ops=[
                            Gt()],
                        comparators=[
                            Constant(value=5)]),
                    Compare(
                        left=Name(id='n', ctx=Load()),
                        ops=[
                            Lt()],
                        comparators=[
                            Constant(value=10)])],
                is_async=0)]))

>>> print(ast.dump(ast.parse('[i async for i in soc]', mode='eval'),
...                indent=4)) # Async comprehension
Expression(
    body=ListComp(
        elt=Name(id='i', ctx=Load()),
        generators=[
            comprehension(
                target=Name(id='i', ctx=Store()),
                iter=Name(id='soc', ctx=Load()),
                ifs=[],
                is_async=1)]))

Операторы

class ast.Assign(targets, value, type_comment)

Присваивание. targets — список узлов, а value — единственный узел.

Несколько узлов в targets представляют присваивание одного и того же значения каждому. Распаковка представлена помещением Tuple или List в targets.

type_comment

type_comment — это необязательная строка с аннотацией типа в виде комментария.

>>> print(ast.dump(ast.parse('a = b = 1'), indent=4)) # Multiple assignment
Module(
    body=[
        Assign(
            targets=[
                Name(id='a', ctx=Store()),
                Name(id='b', ctx=Store())],
            value=Constant(value=1))],
    type_ignores=[])

>>> print(ast.dump(ast.parse('a,b = c'), indent=4)) # Unpacking
Module(
    body=[
        Assign(
            targets=[
                Tuple(
                    elts=[
                        Name(id='a', ctx=Store()),
                        Name(id='b', ctx=Store())],
                    ctx=Store())],
            value=Name(id='c', ctx=Load()))],
    type_ignores=[])
class ast.AnnAssign(target, annotation, value, simple)

Присваивание с аннотацией типа. target — один узел и может быть Name, Attribute или Subscript. annotation — аннотация, например, узел Constant или Name. value — один необязательный узел. simple — булево целое число, установленное в True для узла Name в target , которые не встречаются между скобками и, следовательно, являются чистыми именами, а не выражениями.

>>> print(ast.dump(ast.parse('c: int'), indent=4))
Module(
    body=[
        AnnAssign(
            target=Name(id='c', ctx=Store()),
            annotation=Name(id='int', ctx=Load()),
            simple=1)],
    type_ignores=[])

>>> print(ast.dump(ast.parse('(a): int = 1'), indent=4)) # Annotation with parenthesis
Module(
    body=[
        AnnAssign(
            target=Name(id='a', ctx=Store()),
            annotation=Name(id='int', ctx=Load()),
            value=Constant(value=1),
            simple=0)],
    type_ignores=[])

>>> print(ast.dump(ast.parse('a.b: int'), indent=4)) # Attribute annotation
Module(
    body=[
        AnnAssign(
            target=Attribute(
                value=Name(id='a', ctx=Load()),
                attr='b',
                ctx=Store()),
            annotation=Name(id='int', ctx=Load()),
            simple=0)],
    type_ignores=[])

>>> print(ast.dump(ast.parse('a[1]: int'), indent=4)) # Subscript annotation
Module(
    body=[
        AnnAssign(
            target=Subscript(
                value=Name(id='a', ctx=Load()),
                slice=Constant(value=1),
                ctx=Store()),
            annotation=Name(id='int', ctx=Load()),
            simple=0)],
    type_ignores=[])
class ast.AugAssign(target, op, value)

Расширенное присваивание, например, a += 1. В приведенном ниже примере target — узел Name для x (с контекстом Store), op — Add, а value — Constant со значением 1.

Атрибут target не может быть класса Tuple или List, в отличие от целей Assign.

>>> print(ast.dump(ast.parse('x += 2'), indent=4))
Module(
    body=[
        AugAssign(
            target=Name(id='x', ctx=Store()),
            op=Add(),
            value=Constant(value=2))],
    type_ignores=[])
class ast.Raise(exc, cause)

Оператор raise. exc — объект исключения, который необходимо поднять, обычно Call или Name, или None для самостоятельного raise. cause — необязательная часть для y в raise x from y.

>>> print(ast.dump(ast.parse('raise x from y'), indent=4))
Module(
    body=[
        Raise(
            exc=Name(id='x', ctx=Load()),
            cause=Name(id='y', ctx=Load()))],
    type_ignores=[])
class ast.Assert(test, msg)

Утверждение. test содержит условие, например, узел Compare. msg содержит сообщение об ошибке.

>>> print(ast.dump(ast.parse('assert x,y'), indent=4))
Module(
    body=[
        Assert(
            test=Name(id='x', ctx=Load()),
            msg=Name(id='y', ctx=Load()))],
    type_ignores=[])
class ast.Delete(targets)

Представляет оператор del. targets — список узлов, например, Name, Attribute или Subscript узлы.

>>> print(ast.dump(ast.parse('del x,y,z'), indent=4))
Module(
    body=[
        Delete(
            targets=[
                Name(id='x', ctx=Del()),
                Name(id='y', ctx=Del()),
                Name(id='z', ctx=Del())])],
    type_ignores=[])
class ast.Pass

Оператор pass.

>>> print(ast.dump(ast.parse('pass'), indent=4))
Module(
    body=[
        Pass()],
    type_ignores=[])

Другие операторы, которые применимы только внутри функций или циклов, описаны в других разделах.

Импорты

class ast.Import(names)

Оператор импорта. names — список узлов alias.

>>> print(ast.dump(ast.parse('import x,y,z'), indent=4))
Module(
    body=[
        Import(
            names=[
                alias(name='x'),
                alias(name='y'),
                alias(name='z')])],
    type_ignores=[])
class ast.ImportFrom(module, names, level)

Представляет from x import y. module — строка имени «from» без ведущих точек, или None для операторов, таких как from . import foo. level — целое число, содержащее уровень относительного импорта (0 означает абсолютный импорт).

>>> print(ast.dump(ast.parse('from y import x,y,z'), indent=4))
Module(
    body=[
        ImportFrom(
            module='y',
            names=[
                alias(name='x'),
                alias(name='y'),
                alias(name='z')],
            level=0)],
    type_ignores=[])
class ast.alias(name, asname)

Оба параметра — это строковые имена. asname может быть None , если нужно использовать обычное имя.

>>> print(ast.dump(ast.parse('from ..foo.bar import a as b, c'), indent=4))
Module(
    body=[
        ImportFrom(
            module='foo.bar',
            names=[
                alias(name='a', asname='b'),
                alias(name='c')],
            level=2)],
    type_ignores=[])

Управление потоком

Примечание

Необязательные части, такие как else , хранятся в виде пустого списка, если они отсутствуют.

class ast.If(test, body, orelse)

Оператор if. test содержит единственный узел, например, узел Compare. body и orelse содержат списки узлов.

Дополнительные условия не имеют специального представления в AST, а вместо этого появляются как дополнительные узлы If в разделе orelse предыдущего.

>>> print(ast.dump(ast.parse("""
... if x:
...    ...
... elif y:
...    ...
... else:
...    ...
... """), indent=4))
Module(
    body=[
        If(
            test=Name(id='x', ctx=Load()),
            body=[
                Expr(
                    value=Constant(value=Ellipsis))],
            orelse=[
                If(
                    test=Name(id='y', ctx=Load()),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))],
                    orelse=[
                        Expr(
                            value=Constant(value=Ellipsis))])])],
    type_ignores=[])
class ast.For(target, iter, body, orelse, type_comment)

Цикл for. target содержит переменные, которым присваивает цикл, как единственный узел Name, Tuple или List. iter содержит элемент, по которому итерируется цикл, также как единственный узел. body и orelse содержат списки узлов для выполнения. Те, что в orelse , выполняются, если цикл завершается нормально, а не с помощью оператора break.

type_comment

type_comment — это необязательная строка с аннотацией типа в виде комментария.

>>> print(ast.dump(ast.parse("""
... for x in y:
...     ...
... else:
...     ...
... """), indent=4))
Module(
    body=[
        For(
            target=Name(id='x', ctx=Store()),
            iter=Name(id='y', ctx=Load()),
            body=[
                Expr(
                    value=Constant(value=Ellipsis))],
            orelse=[
                Expr(
                    value=Constant(value=Ellipsis))])],
    type_ignores=[])
class ast.While(test, body, orelse)

Цикл while. test содержит условие, например, узел Compare.

>> print(ast.dump(ast.parse("""
... while x:
...    ...
... else:
...    ...
... """), indent=4))
Module(
    body=[
        While(
            test=Name(id='x', ctx=Load()),
            body=[
                Expr(
                    value=Constant(value=Ellipsis))],
            orelse=[
                Expr(
                    value=Constant(value=Ellipsis))])],
    type_ignores=[])
class ast.Break
class ast.Continue

Операторы break и continue.

>>> print(ast.dump(ast.parse("""\
... for a in b:
...     if a > 5:
...         break
...     else:
...         continue
...
... """), indent=4))
Module(
    body=[
        For(
            target=Name(id='a', ctx=Store()),
            iter=Name(id='b', ctx=Load()),
            body=[
                If(
                    test=Compare(
                        left=Name(id='a', ctx=Load()),
                        ops=[
                            Gt()],
                        comparators=[
                            Constant(value=5)]),
                    body=[
                        Break()],
                    orelse=[
                        Continue()])],
            orelse=[])],
    type_ignores=[])
class ast.Try(body, handlers, orelse, finalbody)

Блоки try. Все атрибуты являются списками узлов для выполнения, за исключением handlers, который является списком узлов ExceptHandler.

>>> print(ast.dump(ast.parse("""
... try:
...    ...
... except Exception:
...    ...
... except OtherException as e:
...    ...
... else:
...    ...
... finally:
...    ...
... """), indent=4))
Module(
    body=[
        Try(
            body=[
                Expr(
                    value=Constant(value=Ellipsis))],
            handlers=[
                ExceptHandler(
                    type=Name(id='Exception', ctx=Load()),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))]),
                ExceptHandler(
                    type=Name(id='OtherException', ctx=Load()),
                    name='e',
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))])],
            orelse=[
                Expr(
                    value=Constant(value=Ellipsis))],
            finalbody=[
                Expr(
                    value=Constant(value=Ellipsis))])],
    type_ignores=[])
class ast.ExceptHandler(type, name, body)

Одиночное except условие. type — это тип исключения, которому он будет соответствовать, обычно узел Name (или None для универсального except: условия). name — строка с именем для хранения исключения, или None , если в условии нет as foo. body — список узлов.

>>> print(ast.dump(ast.parse("""\
... try:
...     a + 1
... except TypeError:
...     pass
... """), indent=4))
Module(
    body=[
        Try(
            body=[
                Expr(
                    value=BinOp(
                        left=Name(id='a', ctx=Load()),
                        op=Add(),
                        right=Constant(value=1)))],
            handlers=[
                ExceptHandler(
                    type=Name(id='TypeError', ctx=Load()),
                    body=[
                        Pass()])],
            orelse=[],
            finalbody=[])],
    type_ignores=[])
class ast.With(items, body, type_comment)

Блок with. items — список узлов withitem, представляющих обработчики контекста, а body — отстуженный блок внутри контекста.

type_comment

type_comment — это необязательная строка с аннотацией типа в виде комментария.

class ast.withitem(context_expr, optional_vars)

Один обработчик контекста в блоке with. context_expr — обработчик контекста, часто узел Call. optional_vars — Name, Tuple или List для части as foo или None , если она не используется.

>>> print(ast.dump(ast.parse("""\
... with a as b, c as d:
...    something(b, d)
... """), indent=4))
Module(
    body=[
        With(
            items=[
                withitem(
                    context_expr=Name(id='a', ctx=Load()),
                    optional_vars=Name(id='b', ctx=Store())),
                withitem(
                    context_expr=Name(id='c', ctx=Load()),
                    optional_vars=Name(id='d', ctx=Store()))],
            body=[
                Expr(
                    value=Call(
                        func=Name(id='something', ctx=Load()),
                        args=[
                            Name(id='b', ctx=Load()),
                            Name(id='d', ctx=Load())],
                        keywords=[]))])],
    type_ignores=[])

Определения функций и классов

class ast.FunctionDef(name, args, body, decorator_list, returns, type_comment)

Определение функции.

  • name — это строка имени функции.
  • args — это узел arguments.
  • body — список узлов внутри функции.
  • decorator_list — список декораторов, которые нужно применить, хранящихся снаружи вовнутрь (т.е. первый в списке будет применён последним).
  • returns — аннотация возвращаемого значения.
type_comment

type_comment — это необязательная строка с аннотацией типа в виде комментария.

class ast.Lambda(args, body)

lambda — это минимальное определение функции, которое можно использовать внутри выражения. В отличие от FunctionDef, body содержит один узел.

>>> print(ast.dump(ast.parse('lambda x,y: ...'), indent=4))
Module(
    body=[
        Expr(
            value=Lambda(
                args=arguments(
                    posonlyargs=[],
                    args=[
                        arg(arg='x'),
                        arg(arg='y')],
                    kwonlyargs=[],
                    kw_defaults=[],
                    defaults=[]),
                body=Constant(value=Ellipsis)))],
    type_ignores=[])
class ast.arguments(posonlyargs, args, vararg, kwonlyargs, kw_defaults, kwarg, defaults)

Аргументы функции.

  • posonlyargs, args и kwonlyargs — списки узлов arg.
  • vararg и kwarg — отдельные узлы arg, относящиеся к параметрам *args, **kwargs.
  • kw_defaults — список значений по умолчанию для ключевых аргументов. Если какой-либо из них None, соответствующий аргумент является обязательным.
  • defaults — список значений по умолчанию для аргументов, которые можно передавать позиционно. Если значений по умолчанию меньше, они соответствуют последним n аргументам.
class ast.arg(arg, annotation, type_comment)

Один аргумент в списке. arg — это строка имени аргумента, annotation — его аннотация, например, узел Str или Name.

type_comment

type_comment — это необязательная строка с аннотацией типа в виде комментария.

>>> print(ast.dump(ast.parse("""\
... @decorator1
... @decorator2
... def f(a: 'annotation', b=1, c=2, *d, e, f=3, **g) -> 'return annotation':
...     pass
... """), indent=4))
Module(
    body=[
        FunctionDef(
            name='f',
            args=arguments(
                posonlyargs=[],
                args=[
                    arg(
                        arg='a',
                        annotation=Constant(value='annotation')),
                    arg(arg='b'),
                    arg(arg='c')],
                vararg=arg(arg='d'),
                kwonlyargs=[
                    arg(arg='e'),
                    arg(arg='f')],
                kw_defaults=[
                    None,
                    Constant(value=3)],
                kwarg=arg(arg='g'),
                defaults=[
                    Constant(value=1),
                    Constant(value=2)]),
            body=[
                Pass()],
            decorator_list=[
                Name(id='decorator1', ctx=Load()),
                Name(id='decorator2', ctx=Load())],
            returns=Constant(value='return annotation'))],
    type_ignores=[])
class ast.Return(value)

Оператор return.

>>> print(ast.dump(ast.parse('return 4'), indent=4))
Module(
    body=[
        Return(
            value=Constant(value=4))],
    type_ignores=[])
class ast.Yield(value)
class ast.YieldFrom(value)

Выражение yield или yield from. Поскольку это выражения, их необходимо обернуть в узел Expr, если возвращаемое значение не используется.

>>> print(ast.dump(ast.parse('yield x'), indent=4))
Module(
    body=[
        Expr(
            value=Yield(
                value=Name(id='x', ctx=Load())))],
    type_ignores=[])

>>> print(ast.dump(ast.parse('yield from x'), indent=4))
Module(
    body=[
        Expr(
            value=YieldFrom(
                value=Name(id='x', ctx=Load())))],
    type_ignores=[])
class ast.Global(names)
class ast.Nonlocal(names)

Операторы global и nonlocal. names — это список строк.

>>> print(ast.dump(ast.parse('global x,y,z'), indent=4))
Module(
    body=[
        Global(
            names=[
                'x',
                'y',
                'z'])],
    type_ignores=[])

>>> print(ast.dump(ast.parse('nonlocal x,y,z'), indent=4))
Module(
    body=[
        Nonlocal(
            names=[
                'x',
                'y',
                'z'])],
    type_ignores=[])
class ast.ClassDef(name, bases, keywords, starargs, kwargs, body, decorator_list)

Определение класса.

  • name — строка имени класса.
  • bases — список узлов для явно указанных базовых классов.
  • keywords — список узлов keyword, главным образом для ‘metaclass’. Другие ключевые слова будут переданы метаклассу в соответствии с PEP-3115.
  • starargs и kwargs — каждый из них — один узел, как и в вызове функции. starargs будет добавлен к списку базовых классов, а kwargs — передан метаклассу.
  • body — список узлов, представляющих код внутри определения класса.
  • decorator_list — список узлов, как в FunctionDef.
>>> print(ast.dump(ast.parse("""\
... @decorator1
... @decorator2
... class Foo(base1, base2, metaclass=meta):
...     pass
... """), indent=4))
Module(
    body=[
        ClassDef(
            name='Foo',
            bases=[
                Name(id='base1', ctx=Load()),
                Name(id='base2', ctx=Load())],
            keywords=[
                keyword(
                    arg='metaclass',
                    value=Name(id='meta', ctx=Load()))],
            body=[
                Pass()],
            decorator_list=[
                Name(id='decorator1', ctx=Load()),
                Name(id='decorator2', ctx=Load())])],
    type_ignores=[])

Асинхронные и ожидания

class ast.AsyncFunctionDef(name, args, body, decorator_list, returns, type_comment)

Определение async def функции. Имеет те же поля, что и FunctionDef.

class ast.Await(value)

Выражение await. value — то, что ожидает. Действителен только в теле AsyncFunctionDef.

>>> print(ast.dump(ast.parse("""\
... async def f():
...     await other_func()
... """), indent=4))
Module(
    body=[
        AsyncFunctionDef(
            name='f',
            args=arguments(
                posonlyargs=[],
                args=[],
                kwonlyargs=[],
                kw_defaults=[],
                defaults=[]),
            body=[
                Expr(
                    value=Await(
                        value=Call(
                            func=Name(id='other_func', ctx=Load()),
                            args=[],
                            keywords=[])))],
            decorator_list=[])],
    type_ignores=[])
class ast.AsyncFor(target, iter, body, orelse, type_comment)
class ast.AsyncWith(items, body, type_comment)

Циклы async for и async with менеджеры контекста. Они имеют те же поля, что и For и With соответственно. Действительны только в теле AsyncFunctionDef.

Примечание

При разборе строки с помощью ast.parse(), узлы операторов (подклассы ast.operator, ast.unaryop, ast.cmpop, ast.boolop и ast.expr_context%) в возвращённом дереве будут одиночными. Изменения в одном из них будут отражаться во всех других экземплярах того же значения (например, ast.Add).

ast Помощники

Помимо классов узлов, модуль ast определяет эти служебные функции и классы для обхода абстрактных синтаксических деревьев:

ast.parse(source, filename='<unknown>', mode='exec', *, type_comments=False, feature_version=None)

Разбор исходного текста в узел AST. Эквивалентно compile(source, filename, mode, ast.PyCF_ONLY_AST).

Если type_comments=True задано, анализатор модифицируется для проверки и возврата комментариев типов, как указано в PEP 484 и PEP 526. Это эквивалентно добавлению ast.PyCF_TYPE_COMMENTS к флагам, переданным в compile(). Это сообщит о синтаксических ошибках для неправильно размещенных комментариев типов. Без этого флага комментарии типов будут игнорироваться, и поле type_comment в выбранных узлах AST всегда будет None. Кроме того, местоположения комментариев # type: ignore будут возвращены в качестве атрибута type_ignores узла Module (в противном случае это всегда будет пустой список).

Кроме того, если mode равно 'func_type', синтаксис входных данных модифицируется в соответствии с PEP 484 «комментариями типов сигнатуры», например (str, int) -> List[str].

Также, установка feature_version в кортеж (major, minor) попытается выполнить разбор с грамматикой этой версии Python. В настоящее время major должен быть равен 3. Например, установка feature_version=(3, 4) позволит использовать async и await в качестве имён переменных. Наименьшая поддерживаемая версия — (3, 4); наибольшая — sys.version_info[0:2].

Если исходный код содержит нулевой символ (‘0’), возбуждается исключение ValueError.

Предупреждение

Обратите внимание, что успешное разбор исходного кода в объект AST не гарантирует, что предоставленный исходный код является корректным кодом Python, который можно выполнить, так как этап компиляции может вызвать дополнительные исключения SyntaxError. Например, исходный код return 42 генерирует допустимый узел AST для оператора return, но его нельзя скомпилировать отдельно (он должен находиться внутри узла функции).

В частности, ast.parse() не будет выполнять проверки области видимости, которые выполняются на этапе компиляции.

Предупреждение

Существует возможность аварийного завершения интерпретатора Python при использовании достаточно длинной/сложной строки из-за ограничений глубины стека в компиляторе AST Python.

Изменено в версии 3.8: Добавлены type_comments, mode='func_type' и feature_version.

ast.unparse(ast_obj)

Распарсить объект ast.AST и сгенерировать строку с кодом, который создаст эквивалентный объект ast.AST, если его повторно разберут с помощью ast.parse().

Предупреждение

Сгенерированная строка кода не обязательно будет равна исходному коду, который сгенерировал объект ast.AST (без каких-либо оптимизаций компилятора, таких как константные кортежи/множества).

Предупреждение

Попытка распарсить очень сложное выражение приведёт к RecursionError.

Введено в версии 3.9.

ast.literal_eval(node_or_string)

Безопасно оценить узел выражения или строку, содержащую Python-литерал или представление контейнера. Предоставленная строка или узел могут содержать только следующие структуры Python-литералов: строки, байты, числа, кортежи, списки, словари, множества, булевы значения и None.

Это можно использовать для безопасной оценки строк, содержащих значения Python из ненадежных источников, без необходимости самостоятельного разбора значений. Он не способен оценивать произвольно сложные выражения, например, включающие операторы или индексирование.

Предупреждение

Существует возможность аварийного завершения интерпретатора Python при использовании достаточно длинной/сложной строки из-за ограничений глубины стека в компиляторе AST Python.

Изменено в версии 3.2: Теперь допускаются литералы байтов и множеств.

Изменено в версии 3.9: Теперь поддерживается создание пустых множеств с помощью 'set()'.

ast.get_docstring(node, clean=True)

Возвращает строку документации заданного узла node (который должен быть узлом FunctionDef, AsyncFunctionDef, ClassDef или Module узлом), или None в случае отсутствия строки документации. Если clean равно true, отформатировать отступы строки документации с помощью inspect.cleandoc().

Изменено в версии 3.5: Теперь поддерживается AsyncFunctionDef.

ast.get_source_segment(source, node, *, padded=False)

Получить фрагмент исходного кода source, который сгенерировал node. Если отсутствует какая-либо информация о местоположении (lineno, end_lineno, col_offset, или end_col_offset ), вернуть None.

Если padded равно True, первая строка многострочного оператора будет дополнена пробелами для соответствия её исходному положению.

Введено в версии 3.8.

ast.fix_missing_locations(node)

При компиляции дерева узлов с помощью compile(), компилятор ожидает атрибутов lineno и col_offset для каждого узла, который их поддерживает. Это довольно утомительно для заполнения для сгенерированных узлов, поэтому этот помощник добавляет эти атрибуты рекурсивно, если они ещё не установлены, устанавливая их значениями родительского узла. Он работает рекурсивно, начиная с node.

ast.increment_lineno(node, n=1)

Увеличить номер строки и конечный номер строки каждого узла в дереве, начиная с node на n. Это полезно для «перемещения кода» в другое место в файле.

ast.copy_location(new_node, old_node)

Скопировать информацию о местоположении (lineno, col_offset, end_lineno, и end_col_offset ) из old_node в new_node, если возможно, и вернуть new_node.

ast.iter_fields(node)

Возвращает кортеж из (fieldname, value) для каждого поля в node._fields , присутствующего в node.

ast.iter_child_nodes(node)

Возвращает все дочерние узлы node, то есть все поля, которые являются узлами, и все элементы полей, которые являются списками узлов.

ast.walk(node)

Рекурсивно возвращает все дочерние узлы в дереве, начиная с node (включая node сам по себе), в произвольном порядке. Это полезно, если вы хотите только изменить узлы на месте и не заботитесь о контексте.

class ast.NodeVisitor

Базовый класс посетителя узлов, который обходит абстрактное синтаксическое дерево и вызывает функцию-посетителя для каждого найденного узла. Эта функция может возвращать значение, которое передаётся методом visit().

Этот класс предназначен для наследования, при этом подкласс добавляет методы-посетители.

visit(node)

Посещение узла. По умолчанию вызывается метод, называемый self.visit_classname, где classname — имя класса узла, или generic_visit(), если такого метода не существует.

generic_visit(node)

Этот посетитель вызывает visit() для всех дочерних узлов узла.

Обратите внимание, что дочерние узлы узлов, у которых есть собственный метод посетителя, не будут посещены, если посетитель не вызывает generic_visit() или не посещает их самостоятельно.

Не используйте NodeVisitor, если вы хотите применять изменения к узлам во время обхода. Для этого существует специальный посетитель (NodeTransformer), который позволяет изменять узлы.

Устарело начиная с версии 3.8: Методы visit_Num(), visit_Str(), visit_Bytes(), visit_NameConstant() и visit_Ellipsis() сейчас устарели и не будут вызываться в будущих версиях Python. Добавьте метод visit_Constant() для обработки всех узлов констант.

class ast.NodeTransformer

Подкласс NodeVisitor, который обходит абстрактное синтаксическое дерево и позволяет изменять узлы.

Класс NodeTransformer будет обходить АСТ и использовать возвращаемое значение методов посетителей для замены или удаления старого узла. Если возвращаемое значение метода посетителя — None, узел будет удалён из его расположения, в противном случае он заменяется возвращаемым значением. Возвращаемое значение может быть исходным узлом, в этом случае замена не происходит.

Вот пример трансформатора, который переписывает все случаи поиска имени (foo) на data['foo']:

class RewriteName(NodeTransformer):

    def visit_Name(self, node):
        return Subscript(
            value=Name(id='data', ctx=Load()),
            slice=Constant(value=node.id),
            ctx=node.ctx
        )

Помните, что если у узла, с которым вы работаете, есть дочерние узлы, вы должны либо преобразовать дочерние узлы самостоятельно, либо сначала вызвать метод generic_visit() для узла.

Для узлов, которые были частью набора операторов (это относится ко всем узлам операторов), посетитель также может вернуть список узлов, а не только один узел.

Если NodeTransformer создаёт новые узлы (которые не были частью исходного дерева) без указания информации о расположении (например, lineno), необходимо вызвать fix_missing_locations() с новым поддеревом для перерасчёта информации о расположении:

tree = ast.parse('foo', mode='eval')
new_tree = fix_missing_locations(RewriteName().visit(tree))

Обычно вы используете трансформатор так:

node = YourTransformer().visit(node)
ast.dump(node, annotate_fields=True, include_attributes=False, *, indent=None)

Возвращает отформатированный вывод дерева в узле node. Это в основном полезно для отладки. Если annotate_fields имеет значение true (по умолчанию), возвращаемая строка покажет имена и значения полей. Если annotate_fields имеет значение false, результирующая строка будет более компактной, опуская явные имена полей. Атрибуты, такие как номера строк и смещения столбцов, по умолчанию не выводились. Если это необходимо, include_attributes можно установить в true.

Если indent является неотрицательным целым числом или строкой, дерево будет отформатировано с указанным уровнем отступа. Уровень отступа 0, отрицательный или "" будет вставлять только новые строки. None (по умолчанию) выбирает однострочное представление. Использование положительного целого числа в качестве отступа увеличивает отступ на заданное количество пробелов на каждом уровне. Если indent является строкой (например, "\t"), эта строка используется для отступа каждого уровня.

Изменено в версии 3.9: Добавлен параметр indent.

Флаги компилятора

Следующие флаги могут быть переданы в compile() для изменения влияния на компиляцию программы:

ast.PyCF_ALLOW_TOP_LEVEL_AWAIT

Включает поддержку операторов ожиданий верхнего уровня await, async for, async with и асинхронных генераторов.

Добавлена в версии 3.8.

ast.PyCF_ONLY_AST

Создаёт и возвращает абстрактное синтаксическое дерево вместо возвращения объекта скомпилированного кода.

ast.PyCF_TYPE_COMMENTS

Включает поддержку комментариев к типам в стиле PEP 484 и PEP 526 (# type: <type>, # type: ignore <stuff>).

Добавлена в версии 3.8.

Использование в командной строке

Добавлена в версии 3.9.

Модуль ast может быть запущен как скрипт из командной строки. Это просто:

python -m ast [-m <mode>] [-a] [infile]

Принимаются следующие параметры:

-h, --help

Показать сообщение справки и выйти.

-m <mode>
--mode <mode>

Указывает, какой тип кода необходимо скомпилировать, как аргумент mode в parse().

--no-type-comments

Не анализировать комментарии к типам.

-a, --include-attributes

Включить атрибуты, такие как номера строк и смещения столбцов.

-i <indent>
--indent <indent>

Отступ узлов в АСТ (количество пробелов).

Если указан infile, его содержимое будет проанализировано для создания АСТ и выведено в стандартный вывод. В противном случае содержимое будет считано из стандартного ввода.

См. также

Green Tree Snakes, внешний ресурс документации, содержит подробную информацию о работе с АСТ Python.

ASTTokens аннотирует АСТ Python позициями токенов и текстом в исходном коде, который их породил. Это полезно для инструментов, производящих трансформации исходного кода.

leoAst.py объединяет основанные на токенах и на деревьях синтаксического анализа представления программ Python, устанавливая двусторонние связи между токенами и узлами АСТ.

LibCST анализирует код как дерево конкретного синтаксиса (Concrete Syntax Tree), которое выглядит как дерево АСТ и сохраняет все детали форматирования. Это полезно для создания автоматизированных приложений рефакторинга (codemod) и линтеров.

Parso — это анализатор Python, поддерживающий восстановление ошибок и обратное разбор для разных версий Python (в нескольких версиях Python). Parso также может перечислить несколько синтаксических ошибок в вашем файле Python.

© 2001–2022 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.9/library/ast.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API