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(), когда режим равен "eval".

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

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

Единственный ввод в интерактивном режиме, как в Интерактивном режиме. Тип узла генерируется ast.parse(), когда режим равен "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(), когда режим равен "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, а также неизменяемыми контейнерными типами (кортежи и замороженные множества), если все их элементы являются константами.

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

Вызов функции. 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 создаётся оператором присваивания выражений (также известным как оператор walrus). В отличие от узла Assign, где первый аргумент может быть несколькими узлами, в этом случае и target, и value должны быть одиночными узлами.

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

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

class ast.Subscript(value, slice, ctx)

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

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

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

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

Сжатия

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

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

generators — список узлов comprehension.

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

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

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

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

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

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

Операторы

class ast.Assign(targets, value, type_comment)

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

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

type_comment

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Оператор pass.

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

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

Импорты

class ast.Import(names)

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

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

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

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

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

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

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

Примечание

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

class ast.If(test, body, orelse)

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

Предложения 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 содержит список узлов, которые нужно выполнить, если шаблон совпадёт и результат вычисления выражения-условия будет истинным.

>>> 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 — это узел выражения. Разрешенные узлы значения ограничены, как описано в документации по оператору match. Этот шаблон успешно выполняется, если объект соответствует вычисленному значению.

>>> 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 — необязательное имя для захвата оставшихся элементов отображения. Разрешенные ключи выражений ограничены, как описано в документации по оператору match.

Этот шаблон выполняется успешно, если объект является отображением, все вычисленные ключи выражений присутствуют в отображении, и значение, соответствующее каждому ключу, соответствует соответствующему подшаблону. Если 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, для сопоставления узла шаблона с экземпляром, который сопоставляется. Несколько встроенных типов также сопоставляются таким образом, как описано в документации по оператору match.

>>> 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 — список значений по умолчанию для ключевых аргументов. Если значение отсутствует, соответствующий аргумент обязателен.
  • 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, в основном для «метакласса». Другие ключевые слова будут переданы метаклассу в соответствии с 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=[])

Асинхронные и ожидающие операции

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) в возвращенном дереве будут являться одиночными экземплярами. Изменения одного будут отражаться во всех других occurrences такого же значения (например, 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 (без каких-либо оптимизаций компилятора, таких как константные кортежи/frozensets).

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

Попытка десериализовать очень сложное выражение приведёт к 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.

END_OF_DOCUMENT_MARKER
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, дерево будет красиво отформатировано с указанным уровнем отступа. Уровень отступа 0, отрицательный или "" будет вставлять только новые строки. None (по умолчанию) выбирает представление на одной строке. Использование положительного целого числа indent вставляет столько пробелов на каждый уровень. Если 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 и выводится в стандартный вывод. В противном случае содержимое считывается со стандартного ввода.

См. также

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

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

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

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

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

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

Spec-Zone.ru

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