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, type_param* type_params)
          | AsyncFunctionDef(identifier name, arguments args,
                             stmt* body, expr* decorator_list, expr? returns,
                             string? type_comment, type_param* type_params)

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

          | Delete(expr* targets)
          | Assign(expr* targets, expr value, string? type_comment)
          | TypeAlias(expr name, type_param* type_params, expr value)
          | 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)

    type_param = TypeVar(identifier name, expr? bound, expr? default_value)
               | ParamSpec(identifier name, expr? default_value)
               | TypeVarTuple(identifier name, expr? default_value)
               attributes (int lineno, int col_offset, int end_lineno, int end_col_offset)
}

Классы узлов

class ast.AST

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

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

_fields

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

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

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

_field_types

Атрибут _field_types каждого конкретного класса представляет собой словарь, отображающий имена полей (также перечисленных в _fields) на их типы.

>>> ast.TypeVar._field_types
{'name': <class 'str'>, 'bound': ast.expr | None, 'default_value': ast.expr | None}

Added in version 3.13.

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(ast.USub(), ast.Constant(5, lineno=0, col_offset=0),
                   lineno=0, col_offset=0)

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

Изменено в версии 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. Пока же их инстанцирование вернет экземпляр другого класса.

Утратил актуальность с версии 3.13, будет удален в версии 3.15: Предыдущие версии Python позволяли создавать узлы AST, в которых отсутствовали необходимые поля. Аналогично, конструкторы узлов AST позволяли использовать произвольные аргументы ключевых слов, которые устанавливались в качестве атрибутов узла AST, даже если они не соответствовали ни одному из полей узла AST. Это поведение устарело и будет удалено в Python 3.15.

Примечание

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

Корневые узлы

class ast.Module(body, type_ignores)

Модуль Python, как и file input. Тип узла, генерируемый 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))])
class ast.Expression(body)

Одиночный узел Python expression input. Тип узла, генерируемый ast.parse(), когда режим равен "eval".

body - это единственный узел, один из expression types.

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

Одиночный interactive input, как в Интерактивный режим. Тип узла, генерируемый ast.parse(), когда режим равен "single".

тело - это list из statement nodes.

>>> 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 из expression nodes.

Возвращается один expression node.

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

Added in version 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: !r повторное форматирование

    • 97: !a форматирование ascii

  • 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())]),
                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()))])

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

>>> print(ast.dump(ast.parse('del a'), indent=4))
Module(
    body=[
        Delete(
            targets=[
                Name(id='a', ctx=Del())])])
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()))])

Выражения

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())))])
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, представляющих аргументы, передаваемые по ключевому слову.

Аргументы 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)))

Added in version 3.8.

Подпись

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()),
                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()),
                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()),
                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())]),
        generators=[
            comprehension(
                target=Name(id='line', ctx=Store()),
                iter=Name(id='file', ctx=Load()),
                is_async=0),
            comprehension(
                target=Name(id='c', ctx=Store()),
                iter=Name(id='line', ctx=Load()),
                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()),
                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))])

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

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

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

>>> 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)])
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))])
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()))])
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()))])
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())])])
class ast.Pass

Высказывание pass.

>>> print(ast.dump(ast.parse('pass'), indent=4))
Module(
    body=[
        Pass()])
class ast.TypeAlias(name, type_params, value)

Псевдоним type alias, созданный с помощью оператора type. name - это имя псевдонима, type_params - список type parameters, а value - значение псевдонима типа.

>>> print(ast.dump(ast.parse('type Alias = int'), indent=4))
Module(
    body=[
        TypeAlias(
            name=Name(id='Alias', ctx=Store()),
            value=Name(id='int', ctx=Load()))])

Added in version 3.12.

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

Импорт

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

Поток управления

Примечание

Необязательные предложения, такие как 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))])])])
class ast.For(target, iter, body, orelse, type_comment)

Цикл for target содержит переменную(ые), которой(ым) присваивается цикл, в виде одного узла Name, Tuple, List, Attribute или Subscript. 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))])])
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))])])
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()])])])
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))])])
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))])])])

Added in version 3.11.

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

Соответствие образцу

class ast.Match(subject, cases)

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

Added in version 3.10.

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())),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))])])])

Added in version 3.10.

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

Added in version 3.10.

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

Added in version 3.10.

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

Added in version 3.10.

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

Added in version 3.10.

class ast.MatchMapping(keys, patterns, rest)

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

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

>>> 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(rest='rest'),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))])])])

Added in version 3.10.

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))]),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))]),
                match_case(
                    pattern=MatchClass(
                        cls=Name(id='Point3D', ctx=Load()),
                        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))])])])

Added in version 3.10.

class ast.MatchAs(pattern, name)

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

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

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

Added in version 3.10.

class ast.MatchOr(patterns)

Соответствие «или-шаблон». Шаблон «или» поочередно сопоставляет с объектом каждый из своих подшаблонов, пока один из них не будет успешным. Тогда шаблон «или» считается успешным. Если ни один из подшаблонов не достиг успеха, шаблон or терпит неудачу. Атрибут 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))])])])

Added in version 3.10.

Параметры типа

Type parameters может существовать в классах, функциях и псевдонимах типов.

class ast.TypeVar(name, bound, default_value)

A typing.TypeVar. name - имя переменной типа. bound - это ограничение или ограничения, если таковые имеются. Если bound - это Tuple, то он представляет ограничения; в противном случае он представляет ограничение. default_value - значение по умолчанию; если у TypeVar нет значения по умолчанию, этот атрибут будет установлен в None.

>>> print(ast.dump(ast.parse("type Alias[T: int = bool] = list[T]"), indent=4))
Module(
    body=[
        TypeAlias(
            name=Name(id='Alias', ctx=Store()),
            type_params=[
                TypeVar(
                    name='T',
                    bound=Name(id='int', ctx=Load()),
                    default_value=Name(id='bool', ctx=Load()))],
            value=Subscript(
                value=Name(id='list', ctx=Load()),
                slice=Name(id='T', ctx=Load()),
                ctx=Load()))])

Added in version 3.12.

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

class ast.ParamSpec(name, default_value)

A typing.ParamSpec. name - имя спецификации параметра. default_value - значение по умолчанию; если у ParamSpec нет значения по умолчанию, этот атрибут будет установлен в None.

>>> print(ast.dump(ast.parse("type Alias[**P = (int, str)] = Callable[P, int]"), indent=4))
Module(
    body=[
        TypeAlias(
            name=Name(id='Alias', ctx=Store()),
            type_params=[
                ParamSpec(
                    name='P',
                    default_value=Tuple(
                        elts=[
                            Name(id='int', ctx=Load()),
                            Name(id='str', ctx=Load())],
                        ctx=Load()))],
            value=Subscript(
                value=Name(id='Callable', ctx=Load()),
                slice=Tuple(
                    elts=[
                        Name(id='P', ctx=Load()),
                        Name(id='int', ctx=Load())],
                    ctx=Load()),
                ctx=Load()))])

Added in version 3.12.

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

class ast.TypeVarTuple(name, default_value)

A typing.TypeVarTuple. name - имя кортежа переменных типа. default_value - значение по умолчанию; если у TypeVarTuple нет значения по умолчанию, этот атрибут будет установлен в None.

>>> print(ast.dump(ast.parse("type Alias[*Ts = ()] = tuple[*Ts]"), indent=4))
Module(
    body=[
        TypeAlias(
            name=Name(id='Alias', ctx=Store()),
            type_params=[
                TypeVarTuple(
                    name='Ts',
                    default_value=Tuple(ctx=Load()))],
            value=Subscript(
                value=Name(id='tuple', ctx=Load()),
                slice=Tuple(
                    elts=[
                        Starred(
                            value=Name(id='Ts', ctx=Load()),
                            ctx=Load())],
                    ctx=Load()),
                ctx=Load()))])

Added in version 3.12.

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

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

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

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

  • name - необработанная строка имени функции.

  • args является узлом arguments.

  • body - список узлов внутри функции.

  • decorator_list - это список декораторов, которые будут применены, хранящийся крайним (т.е. первый в списке будет применен последним).

  • returns - это аннотация возврата.

  • type_params - это список type parameters.

type_comment

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

Изменено в версии 3.12: Добавлено type_params.

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(
                    args=[
                        arg(arg='x'),
                        arg(arg='y')]),
                body=Constant(value=Ellipsis)))])
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(
                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'))])
class ast.Return(value)

Высказывание return.

>>> print(ast.dump(ast.parse('return 4'), indent=4))
Module(
    body=[
        Return(
            value=Constant(value=4))])
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())))])

>>> print(ast.dump(ast.parse('yield from x'), indent=4))
Module(
    body=[
        Expr(
            value=YieldFrom(
                value=Name(id='x', ctx=Load())))])
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'])])

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

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

  • name - необработанная строка для имени класса

  • bases - список узлов для явно указанных базовых классов.

  • keywords - это список узлов keyword, в основном для „metaclass“. Другие ключевые слова будут переданы в метакласс в соответствии с PEP-3115.

  • body - это список узлов, представляющих код в определении класса.

  • decorator_list - это список узлов, как в FunctionDef.

  • type_params - это список type parameters.

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

Изменено в версии 3.12: Добавлено type_params.

Async и ожидание

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

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

Изменено в версии 3.12: Добавлено type_params.

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(),
            body=[
                Expr(
                    value=Await(
                        value=Call(
                            func=Name(id='other_func', ctx=Load()))))])])
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, optimize=-1)

Разбор источника на узлы AST. Эквивалентно compile(source, filename, mode, flags=FLAGS_VALUE, optimize=optimize), где FLAGS_VALUE - это ast.PyCF_ONLY_AST, если optimize <= 0 и ast.PyCF_OPTIMIZED_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, 7) (и она может увеличиться в будущих версиях Python); самая высокая - sys.version_info[0:2]. Попытка «Best-effort» означает, что нет гарантии, что разбор (или успех разбора) будет таким же, как при выполнении на версии 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.

Изменено в версии 3.13: Минимальной поддерживаемой версией для feature_version теперь является (3, 7). Был добавлен аргумент optimize.

ast.unparse(ast_obj)

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

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

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

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

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

Added in version 3.9.

ast.literal_eval(node_or_string)

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

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

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

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

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

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

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

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

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

ast.get_docstring(node, clean=True)

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

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

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

Получение сегмента исходного кода источника, породившего узел. Если некоторая информация о местоположении (lineno, end_lineno, col_offset или end_col_offset) отсутствует, возвращается None.

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

Added in version 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) из старого_узла в новый_узел, если это возможно, и верните новый_узел.

ast.iter_fields(node)

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

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, show_empty=False)

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

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

Если show_empty имеет значение False (по умолчанию), то пустые списки и поля, имеющие значение None, будут опущены в выводе.

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

Изменено в версии 3.13: Добавлена опция show_empty.

>>> print(ast.dump(ast.parse("""\
... async def f():
...     await other_func()
... """), indent=4, show_empty=True))
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_params=[])],
    type_ignores=[])

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

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

ast.PyCF_ALLOW_TOP_LEVEL_AWAIT

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

Added in version 3.8.

ast.PyCF_ONLY_AST

Генерирует и возвращает абстрактное дерево синтаксиса вместо того, чтобы возвращать объект скомпилированного кода.

ast.PyCF_OPTIMIZED_AST

Возвращаемый AST оптимизируется в соответствии с аргументом optimize в compile() или ast.parse().

Added in version 3.13.

ast.PyCF_TYPE_COMMENTS

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

Added in version 3.8.

ast.compare(a, b, /, *, compare_attributes=False)

Рекурсивно сравнивает два AST.

compare_attributes влияет на то, учитываются ли атрибуты AST при сравнении. Если compare_attributes равно False (по умолчанию), то атрибуты игнорируются. В противном случае все они должны быть равны. Эта опция полезна для проверки того, что AST структурно одинаковы, но различаются пробелами или другими подобными деталями. Атрибуты включают номера строк и смещения столбцов.

Added in version 3.14.

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

Added in version 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, внешний ресурс документации, содержит подробную информацию о работе с Python AST.

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

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

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

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