Spec-Zone.ru › Python 3.11

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)
          | TryStar(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.Module(body, type_ignores)

Модуль Python, как и при вводе из файла. Тип узла, создаваемый функцией ast.parse() в режиме "exec" по умолчанию.

body — это list инструкций модуля.

type_ignores — это list комментариев модуля с указанием игнорировать тип; подробнее см. ast.parse().

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

Отдельное выражение, переданное на вход Python. Тип узла, создаваемый функцией ast.parse(), если mode равен "eval".

body — это отдельный узел, один из типов выражений.

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

Отдельный фрагмент интерактивного ввода, как в интерактивном режиме. Тип узла, создаваемый функцией ast.parse(), если mode равен "single".

body — это list узлов инструкций.

>>> print(ast.dump(ast.parse('x = 1; y = 2', mode='single'), indent=4))
Interactive(
    body=[
        Assign(
            targets=[
                Name(id='x', ctx=Store())],
            value=Constant(value=1)),
        Assign(
            targets=[
                Name(id='y', ctx=Store())],
            value=Constant(value=2))])
class ast.FunctionType(argtypes, returns)

Представление комментариев типов старого формата для функций, поскольку в версиях Python до 3.5 не поддерживались аннотации PEP 484. Тип узла, создаваемый функцией ast.parse(), если mode равен "func_type".

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

def sum_two_number(a, b):
    # type: (int, int) -> int
    return a + b

argtypes — это list узлов выражений.

returns — это отдельный узел выражения.

>>> print(ast.dump(ast.parse('(int, str) -> List[int]', mode='func_type'), indent=4))
FunctionType(
    argtypes=[
        Name(id='int', ctx=Load()),
        Name(id='str', ctx=Load())],
    returns=Subscript(
        value=Name(id='List', ctx=Load()),
        slice=Name(id='int', ctx=Load()),
        ctx=Load()))

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

Литералы

class ast.Constant(value)

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

>>> 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, а в соответствующей позиции списка keys указывается None.

>>> 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)

Логическая операция «or» или «and». 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)

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

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

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

>>> 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.TryStar(body, handlers, orelse, finalbody)

Блоки try, за которыми следуют части except*. Атрибуты те же, что и у Try, но узлы ExceptHandler в handlers рассматриваются как блоки except*, а не как except.

>>> print(ast.dump(ast.parse("""
... try:
...    ...
... except* Exception:
...    ...
... """), indent=4))
Module(
    body=[
        TryStar(
            body=[
                Expr(
                    value=Constant(value=Ellipsis))],
            handlers=[
                ExceptHandler(
                    type=Name(id='Exception', ctx=Load()),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))])],
            orelse=[],
            finalbody=[])],
    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 содержит список узлов, выполняемых, если образец соответствует объекту и результат вычисления выражения-ограничения равен true.

>>> 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)

Образец сопоставления «as», образец захвата или образец-шаблон. 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 — его аннотация, например узел 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, body, decorator_list)

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

  • name — исходная строка с именем класса
  • bases — список узлов для явно указанных базовых классов.
  • keywords — список узлов keyword, в основном для ‘metaclass’. Другие именованные аргументы будут переданы метаклассу согласно PEP-3115.
  • 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=[])

Асинхронное выполнение и await

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. Например, установка feature_version=(3, 9) позволит попытаться запретить разбор операторов match. В настоящее время major должно быть равно 3. Наименьшая поддерживаемая версия — (3, 4) (в будущих версиях Python это значение может увеличиться); наибольшая — sys.version_info[0:2]. Под попыткой «по возможности» подразумевается, что нет гарантии, что результат разбора (или его успешность) будет таким же, как при запуске в версии Python, соответствующей feature_version.

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

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

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

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

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

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

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

ast.unparse(ast_obj)

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

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

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

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

Попытка преобразовать обратно в исходный код очень сложное выражение приведет к исключению RecursionError.

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

ast.literal_eval(node_or_string)

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

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

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

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

Из-за ограничений глубины стека в компиляторе AST Python интерпретатор 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)

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

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() или не посетит их самостоятельно.

visit_Constant(node)

Обрабатывает все узлы-константы.

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

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

class ast.NodeTransformer

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

NodeTransformer обходит AST и использует возвращаемое значение методов посетителя для замены или удаления старого узла. Если метод посетителя возвращает 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>

Отступы узлов AST (количество пробелов).

Если задан infile, его содержимое разбирается в AST, а результат выводится в stdout. В противном случае содержимое считывается из stdin.

См. также

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

ASTTokens дополняет AST Python сведениями о расположении токенов и текста в исходном коде, из которого они были созданы. Это полезно для инструментов преобразования исходного кода.

leoAst.py объединяет представления программ Python на основе токенов и дерева разбора, создавая двусторонние связи между токенами и узлами AST.

LibCST разбирает код в конкретное синтаксическое дерево, похожее на дерево AST и сохраняющее все детали форматирования. Оно полезно для создания приложений автоматического рефакторинга (codemod) и линтеров.

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

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

Spec-Zone.ru

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