Spec-Zone.ru › Python 3.10

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)

          | Match(expr subject, match_case* cases)

          | 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)
             attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)

    withitem = (expr context_expr, expr? optional_vars)

    match_case = (pattern pattern, expr? guard, stmt* body)

    pattern = MatchValue(expr value)
            | MatchSingleton(constant value)
            | MatchSequence(pattern* patterns)
            | MatchMapping(expr* keys, pattern* patterns, identifier? rest)
            | MatchClass(expr cls, pattern* patterns, identifier* kwd_attrs, pattern* kwd_patterns)

            | MatchStar(identifier? name)
            -- The optional "rest" MatchMapping parameter handles capturing extra mapping keys

            | MatchAs(pattern? pattern, identifier? name)
            | MatchOr(pattern* patterns)

             attributes (int lineno, int col_offset, int end_lineno, int end_col_offset)

    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 создаётся оператором присваивания выражений (также известным как оператор «крокодила»). В отличие от узла 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 содержат списки узлов.

Условные части elif не имеют специального представления в 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.Match(subject, cases)

Утверждение match. subject содержит объект, который сопоставляется с различными вариантами, а cases содержит итерируемый список узлов match_case с различными вариантами.

class ast.match_case(pattern, guard, body)

Один случай шаблона в операторе match. pattern содержит шаблон сопоставления, с которым будет сравниваться объект. Обратите внимание, что узлы AST, созданные для шаблонов, отличаются от узлов, созданных для выражений, даже если они имеют одинаковый синтаксис.

Атрибут guard содержит выражение, которое будет вычислено, если шаблон соответствует объекту.

body содержит список узлов, которые будут выполнены, если шаблон соответствует объекту, а результат вычисления выражения условия — истина.

>>> print(ast.dump(ast.parse("""
... match x:
...     case [x] if x>0:
...         ...
...     case tuple():
...         ...
... """), indent=4))
Module(
    body=[
        Match(
            subject=Name(id='x', ctx=Load()),
            cases=[
                match_case(
                    pattern=MatchSequence(
                        patterns=[
                            MatchAs(name='x')]),
                    guard=Compare(
                        left=Name(id='x', ctx=Load()),
                        ops=[
                            Gt()],
                        comparators=[
                            Constant(value=0)]),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))]),
                match_case(
                    pattern=MatchClass(
                        cls=Name(id='tuple', ctx=Load()),
                        patterns=[],
                        kwd_attrs=[],
                        kwd_patterns=[]),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))])])],
    type_ignores=[])
class ast.MatchValue(value)

Шаблон литерала или значения для сравнения по равенству. value — узел выражения. Разрешённые узлы значений ограничены, как описано в документации к оператору сопоставления. Этот шаблон соответствует, если объект сопоставления равен вычисленному значению.

>>> print(ast.dump(ast.parse("""
... match x:
...     case "Relevant":
...         ...
... """), indent=4))
Module(
    body=[
        Match(
            subject=Name(id='x', ctx=Load()),
            cases=[
                match_case(
                    pattern=MatchValue(
                        value=Constant(value='Relevant')),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))])])],
    type_ignores=[])
class ast.MatchSingleton(value)

Шаблон литерала для сравнения по идентичности. value — сравниваемый синглтон: None, True, или False. Этот шаблон соответствует, если объект сопоставления — заданная константа.

>>> print(ast.dump(ast.parse("""
... match x:
...     case None:
...         ...
... """), indent=4))
Module(
    body=[
        Match(
            subject=Name(id='x', ctx=Load()),
            cases=[
                match_case(
                    pattern=MatchSingleton(value=None),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))])])],
    type_ignores=[])
class ast.MatchSequence(patterns)

Шаблон последовательности. patterns содержит шаблоны, которые должны сопоставляться с элементами объекта, если объект является последовательностью. Сопоставляет последовательность переменной длины, если один из подшаблонов — узел MatchStar, в противном случае сопоставляет последовательность фиксированной длины.

>>> print(ast.dump(ast.parse("""
... match x:
...     case [1, 2]:
...         ...
... """), indent=4))
Module(
    body=[
        Match(
            subject=Name(id='x', ctx=Load()),
            cases=[
                match_case(
                    pattern=MatchSequence(
                        patterns=[
                            MatchValue(
                                value=Constant(value=1)),
                            MatchValue(
                                value=Constant(value=2))]),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))])])],
    type_ignores=[])
class ast.MatchStar(name)

Сопоставляет оставшуюся часть последовательности в шаблоне последовательности переменной длины. Если name не None, список, содержащий оставшиеся элементы последовательности, привязывается к этому имени, если шаблон последовательности в целом соответствует.

>>> print(ast.dump(ast.parse("""
... match x:
...     case [1, 2, *rest]:
...         ...
...     case [*_]:
...         ...
... """), indent=4))
Module(
    body=[
        Match(
            subject=Name(id='x', ctx=Load()),
            cases=[
                match_case(
                    pattern=MatchSequence(
                        patterns=[
                            MatchValue(
                                value=Constant(value=1)),
                            MatchValue(
                                value=Constant(value=2)),
                            MatchStar(name='rest')]),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))]),
                match_case(
                    pattern=MatchSequence(
                        patterns=[
                            MatchStar()]),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))])])],
    type_ignores=[])
class ast.MatchMapping(keys, patterns, rest)

Шаблон отображения. keys — последовательность узлов выражения. patterns — соответствующая последовательность узлов шаблонов. rest — необязательное имя, которое можно указать для захвата оставшихся элементов отображения. Разрешённые выражения ключей ограничены, как описано в документации к оператору сопоставления.

Этот шаблон соответствует, если объект — отображение, все вычисленные выражения ключей присутствуют в отображении, а значение, соответствующее каждому ключу, соответствует соответствующему подшаблону. Если rest не None, словарь, содержащий оставшиеся элементы отображения, привязывается к этому имени, если шаблон отображения в целом соответствует.

>>> print(ast.dump(ast.parse("""
... match x:
...     case {1: _, 2: _}:
...         ...
...     case {**rest}:
...         ...
... """), indent=4))
Module(
    body=[
        Match(
            subject=Name(id='x', ctx=Load()),
            cases=[
                match_case(
                    pattern=MatchMapping(
                        keys=[
                            Constant(value=1),
                            Constant(value=2)],
                        patterns=[
                            MatchAs(),
                            MatchAs()]),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))]),
                match_case(
                    pattern=MatchMapping(keys=[], patterns=[], rest='rest'),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))])])],
    type_ignores=[])
class ast.MatchClass(cls, patterns, kwd_attrs, kwd_patterns)

Шаблон класса. cls — выражение, задающее номинальный класс для сопоставления. patterns — последовательность узлов шаблонов, которые должны быть сопоставлены с определённой последовательностью атрибутов класса. kwd_attrs — последовательность дополнительных атрибутов для сопоставления (указанных в качестве аргументов ключевого слова в шаблоне класса), kwd_patterns — соответствующие шаблоны (указанные в качестве значений ключевых слов в шаблоне класса).

Этот шаблон соответствует, если объект является экземпляром указанного класса, все позиционные шаблоны соответствуют соответствующим атрибутам класса и все указанные атрибуты ключевых слов соответствуют своим соответствующим шаблонам.

Примечание: классы могут определять свойство, которое возвращает self, для сопоставления узла шаблона с экземпляром, который сопоставляется. Также нескольких встроенных типов сопоставляются таким способом, как описано в документации к оператору сопоставления.

>>> print(ast.dump(ast.parse("""
... match x:
...     case Point2D(0, 0):
...         ...
...     case Point3D(x=0, y=0, z=0):
...         ...
... """), indent=4))
Module(
    body=[
        Match(
            subject=Name(id='x', ctx=Load()),
            cases=[
                match_case(
                    pattern=MatchClass(
                        cls=Name(id='Point2D', ctx=Load()),
                        patterns=[
                            MatchValue(
                                value=Constant(value=0)),
                            MatchValue(
                                value=Constant(value=0))],
                        kwd_attrs=[],
                        kwd_patterns=[]),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))]),
                match_case(
                    pattern=MatchClass(
                        cls=Name(id='Point3D', ctx=Load()),
                        patterns=[],
                        kwd_attrs=[
                            'x',
                            'y',
                            'z'],
                        kwd_patterns=[
                            MatchValue(
                                value=Constant(value=0)),
                            MatchValue(
                                value=Constant(value=0)),
                            MatchValue(
                                value=Constant(value=0))]),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))])])],
    type_ignores=[])
class ast.MatchAs(pattern, name)

Шаблон «как», шаблон захвата или шаблон-подстановочный знак. pattern содержит шаблон сопоставления, с которым будет сравниваться объект. Если шаблон — None, узел представляет собой шаблон захвата (т. е. простое имя) и всегда соответствует.

Атрибут name содержит имя, которое будет привязано, если шаблон соответствует. Если name — None, pattern также должно быть None, и узел представляет шаблон-подстановочный знак.

>>> print(ast.dump(ast.parse("""
... match x:
...     case [x] as y:
...         ...
...     case _:
...         ...
... """), indent=4))
Module(
    body=[
        Match(
            subject=Name(id='x', ctx=Load()),
            cases=[
                match_case(
                    pattern=MatchAs(
                        pattern=MatchSequence(
                            patterns=[
                                MatchAs(name='x')]),
                        name='y'),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))]),
                match_case(
                    pattern=MatchAs(),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))])])],
    type_ignores=[])
class ast.MatchOr(patterns)

Шаблон «или». Шаблон «или» последовательно сопоставляет каждый свой подшаблон с объектом до тех пор, пока один не совпадёт. В этом случае шаблон «или» считается соответствующим. Если ни один из подшаблонов не соответствует, шаблон «или» не соответствует. Атрибут patterns содержит список узлов шаблонов сопоставления, которые будут сопоставляться с объектом.

>>> print(ast.dump(ast.parse("""
... match x:
...     case [x] | (y):
...         ...
... """), indent=4))
Module(
    body=[
        Match(
            subject=Name(id='x', ctx=Load()),
            cases=[
                match_case(
                    pattern=MatchOr(
                        patterns=[
                            MatchSequence(
                                patterns=[
                                    MatchAs(name='x')]),
                            MatchAs(name='y')]),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))])])],
    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, в основном для «метакласса». Другие ключевые слова будут переданы метаклассу, как в 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 и Ellipsis.

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

В прошлом эта функция документировалась как «безопасная», не определяя, что это значит. Это было вводящим в заблуждение. Это специально разработано для того, чтобы не выполнять код Python, в отличие от более общей функции eval(). Нет пространства имён, нет поиска имён или возможности вызова. Но он не защищён от атак: сравнительно небольшой вход может привести к исчерпанию памяти или переполнению стека C, аварийно завершив процесс. Также существует возможность чрезмерного потребления ЦП для отказа в обслуживании некоторых входных данных. Поэтому вызывать его для ненадёжных данных не рекомендуется.

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

Возможен сбой интерпретатора Python из-за ограничений глубины стека в компиляторе AST Python.

Он может генерировать ValueError, TypeError, SyntaxError, MemoryError и RecursionError в зависимости от некорректного ввода.

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

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

Изменено в версии 3.10: Для строковых входных данных теперь удаляются начальные пробелы и табуляции.

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 само по себе), в произвольном порядке. Это полезно, если вы хотите только изменять узлы на месте и не заботитесь о контексте.

END_OF_DOCUMENT_MARKER
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 отступает на указанное количество пробелов на каждом уровне. Если indent — строка (например, "\t"), эта строка используется для отступа каждого уровня.

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

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

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

ast.PyCF_ALLOW_TOP_LEVEL_AWAIT

Включает поддержку top-level 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, его содержимое будет обработано в АСТ и выведено в stdout. В противном случае содержимое считывается со стандартного ввода.

См. также

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

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

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

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

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

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

Spec-Zone.ru

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