ast — Абстрактные синтаксические деревья¶
Исходный код: Lib/ast.py.
Модуль ast помогает приложениям Python обрабатывать деревья грамматики абстрактного синтаксиса Python. Сам абстрактный синтаксис может меняться с каждым выпуском Python; этот модуль помогает программно узнать, как выглядит текущая грамматика.
Абстрактное синтаксическое дерево может быть сгенерировано путем передачи ast.PyCF_ONLY_AST в качестве флага встроенной функции compile() или с помощью помощника parse(), предоставленного в этом модуле. Результатом будет дерево объектов, все классы которых наследуются от ast.AST. Абстрактное синтаксическое дерево может быть скомпилировано в объект кода Python с помощью встроенной функции compile().
Абстрактная грамматика¶
В настоящее время абстрактная грамматика определяется следующим образом:
-- ASDL's 4 builtin types are:
-- identifier, int, string, constant
module Python
{
mod = Module(stmt* body, type_ignore* type_ignores)
| Interactive(stmt* body)
| Expression(expr body)
| FunctionType(expr* argtypes, expr returns)
stmt = FunctionDef(identifier name, arguments args,
stmt* body, expr* decorator_list, expr? returns,
string? type_comment)
| AsyncFunctionDef(identifier name, arguments args,
stmt* body, expr* decorator_list, expr? returns,
string? type_comment)
| ClassDef(identifier name,
expr* bases,
keyword* keywords,
stmt* body,
expr* decorator_list)
| Return(expr? value)
| Delete(expr* targets)
| Assign(expr* targets, expr value, string? type_comment)
| AugAssign(expr target, operator op, expr value)
-- 'simple' indicates that we annotate simple name without parens
| AnnAssign(expr target, expr annotation, expr? value, int simple)
-- use 'orelse' because else is a keyword in target languages
| For(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment)
| AsyncFor(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment)
| While(expr test, stmt* body, stmt* orelse)
| If(expr test, stmt* body, stmt* orelse)
| With(withitem* items, stmt* body, string? type_comment)
| AsyncWith(withitem* items, stmt* body, string? type_comment)
| Match(expr subject, match_case* cases)
| Raise(expr? exc, expr? cause)
| Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)
| Assert(expr test, expr? msg)
| Import(alias* names)
| ImportFrom(identifier? module, alias* names, int? level)
| Global(identifier* names)
| Nonlocal(identifier* names)
| Expr(expr value)
| Pass | Break | Continue
-- col_offset is the byte offset in the utf8 string the parser uses
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
-- BoolOp() can use left & right?
expr = BoolOp(boolop op, expr* values)
| NamedExpr(expr target, expr value)
| BinOp(expr left, operator op, expr right)
| UnaryOp(unaryop op, expr operand)
| Lambda(arguments args, expr body)
| IfExp(expr test, expr body, expr orelse)
| Dict(expr* keys, expr* values)
| Set(expr* elts)
| ListComp(expr elt, comprehension* generators)
| SetComp(expr elt, comprehension* generators)
| DictComp(expr key, expr value, comprehension* generators)
| GeneratorExp(expr elt, comprehension* generators)
-- the grammar constrains where yield expressions can occur
| Await(expr value)
| Yield(expr? value)
| YieldFrom(expr value)
-- need sequences for compare to distinguish between
-- x < 4 < 3 and (x < 4) < 3
| Compare(expr left, cmpop* ops, expr* comparators)
| Call(expr func, expr* args, keyword* keywords)
| FormattedValue(expr value, int conversion, expr? format_spec)
| JoinedStr(expr* values)
| Constant(constant value, string? kind)
-- the following expression can appear in assignment context
| Attribute(expr value, identifier attr, expr_context ctx)
| Subscript(expr value, expr slice, expr_context ctx)
| Starred(expr value, expr_context ctx)
| Name(identifier id, expr_context ctx)
| List(expr* elts, expr_context ctx)
| Tuple(expr* elts, expr_context ctx)
-- can appear only in Subscript
| Slice(expr? lower, expr? upper, expr? step)
-- col_offset is the byte offset in the utf8 string the parser uses
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
expr_context = Load | Store | Del
boolop = And | Or
operator = Add | Sub | Mult | MatMult | Div | Mod | Pow | LShift
| RShift | BitOr | BitXor | BitAnd | FloorDiv
unaryop = Invert | Not | UAdd | USub
cmpop = Eq | NotEq | Lt | LtE | Gt | GtE | Is | IsNot | In | NotIn
comprehension = (expr target, expr iter, expr* ifs, int is_async)
excepthandler = ExceptHandler(expr? type, identifier? name, stmt* body)
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
arguments = (arg* posonlyargs, arg* args, arg? vararg, arg* kwonlyargs,
expr* kw_defaults, arg? kwarg, expr* defaults)
arg = (identifier arg, expr? annotation, string? type_comment)
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
-- keyword arguments supplied to call (NULL identifier for **kwargs)
keyword = (identifier? arg, expr value)
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
-- import name with optional 'as' alias.
alias = (identifier name, identifier? asname)
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
withitem = (expr context_expr, expr? optional_vars)
match_case = (pattern pattern, expr? guard, stmt* body)
pattern = MatchValue(expr value)
| MatchSingleton(constant value)
| MatchSequence(pattern* patterns)
| MatchMapping(expr* keys, pattern* patterns, identifier? rest)
| MatchClass(expr cls, pattern* patterns, identifier* kwd_attrs, pattern* kwd_patterns)
| MatchStar(identifier? name)
-- The optional "rest" MatchMapping parameter handles capturing extra mapping keys
| MatchAs(pattern? pattern, identifier? name)
| MatchOr(pattern* patterns)
attributes (int lineno, int col_offset, int end_lineno, int end_col_offset)
type_ignore = TypeIgnore(int lineno, string tag)
}
Классы узлов¶
-
class
ast.AST¶ Это основа всех классов узлов AST. Фактические классы узлов являются производными от файла
Parser/Python.asdl, который воспроизводится above. Они определены в модуле_astна языке C и реэкспортированы вast.Для каждого символа левой стороны в абстрактной грамматике определен один класс (например,
ast.stmtилиast.expr). Кроме того, для каждого конструктора правой стороны определен один класс; эти классы наследуются от классов для деревьев левой стороны. Например,ast.BinOpнаследуется отast.expr. Для производственных правил с альтернативами (они же «суммы») класс левой стороны является абстрактным: создаются только экземпляры конкретных узлов конструктора.-
_fields¶ Каждый конкретный класс имеет атрибут
_fields, который дает имена всех дочерних узлов.Каждый экземпляр конкретного класса имеет один атрибут для каждого дочернего узла, тип которого определен в грамматике. Например, экземпляры
ast.BinOpимеют атрибутleftтипаast.expr.Если эти атрибуты помечены в грамматике как необязательные (с помощью знака вопроса), то значение может быть
None. Если атрибуты могут иметь ноль или более значений (помечены звездочкой), то значения представляются в виде списков Python. Все возможные атрибуты должны присутствовать и иметь допустимые значения при компиляции AST с помощьюcompile().
-
lineno¶ -
col_offset¶ -
end_lineno¶ -
end_col_offset¶ Экземпляры подклассов
ast.exprиast.stmtимеют атрибутыlineno,col_offset,end_linenoиend_col_offset.linenoиend_lineno- это номер первой и последней строки исходного текста (1-индексированный, так что первая строка - это строка 1), аcol_offsetиend_col_offset- это соответствующие смещения байтов UTF-8 первой и последней лексемы, породившей узел. Смещение UTF-8 записывается потому, что синтаксический анализатор использует UTF-8 внутри системы.Обратите внимание, что конечные позиции не требуются компилятору и поэтому являются необязательными. Конечное смещение находится после последнего символа, например, можно получить исходный сегмент однострочного узла выражения, используя
source_line[node.col_offset : node.end_col_offset].
Конструктор класса
ast.Tразбирает свои аргументы следующим образом:Если есть позиционные аргументы, их должно быть столько, сколько элементов в
T._fields; они будут назначены как атрибуты этих имен.Если есть аргументы в виде ключевых слов, они установят одноименные атрибуты в заданные значения.
Например, чтобы создать и заполнить узел
ast.UnaryOp, вы можете использоватьnode = ast.UnaryOp() node.op = ast.USub() node.operand = ast.Constant() node.operand.value = 5 node.operand.lineno = 0 node.operand.col_offset = 0 node.lineno = 0 node.col_offset = 0
или более компактный
node = ast.UnaryOp(ast.USub(), ast.Constant(5, lineno=0, col_offset=0), lineno=0, col_offset=0)
-
Изменено в версии 3.8: Класс ast.Constant теперь используется для всех констант.
Изменено в версии 3.9: Простые индексы представлены своим значением, расширенные срезы представлены в виде кортежей.
Не рекомендуется, начиная с версии 3.8: Старые классы ast.Num, ast.Str, ast.Bytes, ast.NameConstant и ast.Ellipsis все еще доступны, но они будут удалены в будущих выпусках Python. Тем временем их инстанцирование будет возвращать экземпляр другого класса.
Не рекомендуется, начиная с версии 3.9: Старые классы ast.Index и ast.ExtSlice все еще доступны, но они будут удалены в будущих выпусках Python. Тем временем их инстанцирование будет возвращать экземпляр другого класса.
Примечание
Представленные здесь описания конкретных классов узлов были первоначально адаптированы из фантастического проекта Green Tree Snakes и всех его участников.
Литература¶
-
class
ast.Constant(value)¶ Постоянное значение. Атрибут
valueлитералаConstantсодержит объект Python, который он представляет. Представляемые значения могут быть простыми типами, такими как число, строка илиNone, а также неизменяемыми контейнерными типами (кортежи и фростенсеты), если все их элементы являются константными.>>> print(ast.dump(ast.parse('123', mode='eval'), indent=4)) Expression( body=Constant(value=123))
-
class
ast.FormattedValue(value, conversion, format_spec)¶ Узел, представляющий одно поле форматирования в f-строке. Если строка содержит одно поле форматирования и больше ничего, узел может быть изолирован, в противном случае он появляется в
JoinedStr.value- это любой узел выражения (например, литерал, переменная или вызов функции).conversion- целое число:-1: без форматирования
115:
!sформатирование строк114:
!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())], 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.Compare(left, ops, comparators)¶ Сравнение двух или более значений.
left- первое значение в сравнении,ops- список операторов, аcomparators- список значений после первого элемента в сравнении.>>> print(ast.dump(ast.parse('1 <= a < 10', mode='eval'), indent=4)) Expression( body=Compare( left=Constant(value=1), ops=[ LtE(), Lt()], comparators=[ Name(id='a', ctx=Load()), Constant(value=10)]))
-
class
ast.Eq¶ -
class
ast.NotEq¶ -
class
ast.Lt¶ -
class
ast.LtE¶ -
class
ast.Gt¶ -
class
ast.GtE¶ -
class
ast.Is¶ -
class
ast.IsNot¶ -
class
ast.In¶ -
class
ast.NotIn¶ Токены оператора сравнения.
-
class
ast.Call(func, args, keywords, starargs, kwargs)¶ Вызов функции.
func- это функция, которая часто будет объектомNameилиAttribute. Аргументы:argsсодержит список аргументов, переданных по позиции.keywordsсодержит список объектовkeyword, представляющих аргументы, переданные ключевым словом.
При создании узла
Callобязательными являютсяargsиkeywords, но они могут быть пустыми списками.starargsиkwargsявляются необязательными.>>> print(ast.dump(ast.parse('func(a, b=c, *d, **e)', mode='eval'), indent=4)) Expression( body=Call( func=Name(id='func', ctx=Load()), args=[ Name(id='a', ctx=Load()), Starred( value=Name(id='d', ctx=Load()), ctx=Load())], keywords=[ keyword( arg='b', value=Name(id='c', ctx=Load())), keyword( value=Name(id='e', ctx=Load()))]))
-
class
ast.keyword(arg, value)¶ Аргумент ключевого слова для вызова функции или определения класса.
arg- необработанная строка имени параметра,value- узел для передачи.
-
class
ast.IfExp(test, body, orelse)¶ Выражение, такое как
a if b else c. Каждое поле содержит один узел, поэтому в следующем примере все три узла являются узламиName.>>> print(ast.dump(ast.parse('a if b else c', mode='eval'), indent=4)) Expression( body=IfExp( test=Name(id='b', ctx=Load()), body=Name(id='a', ctx=Load()), orelse=Name(id='c', ctx=Load())))
-
class
ast.Attribute(value, attr, ctx)¶ Доступ к атрибуту, например,
d.keys.value- это узел, обычноName.attr- это голая строка, дающая имя атрибута, аctx- этоLoad,StoreилиDelв зависимости от того, как действует атрибут.>>> print(ast.dump(ast.parse('snake.colour', mode='eval'), indent=4)) Expression( body=Attribute( value=Name(id='snake', ctx=Load()), attr='colour', ctx=Load()))
-
class
ast.NamedExpr(target, value)¶ Именованное выражение. Этот узел AST создается оператором присваивания выражений (также известным как оператор моржа). В отличие от узла
Assign, в котором первый аргумент может быть несколькими узлами, в данном случае иtarget, иvalueдолжны быть одиночными узлами.>>> print(ast.dump(ast.parse('(x := 4)', mode='eval'), indent=4)) Expression( body=NamedExpr( target=Name(id='x', ctx=Store()), value=Constant(value=4)))
Subscripting¶
-
class
ast.Subscript(value, slice, ctx)¶ Подскрипт, например
l[1].value- это подзаписываемый объект (обычно последовательность или отображение).slice- это индекс, фрагмент или ключ. Он может бытьTupleи содержатьSlice.ctx- этоLoad,StoreилиDelв зависимости от действия, выполняемого с подзаписью.>>> print(ast.dump(ast.parse('l[1:2, 3]', mode='eval'), indent=4)) Expression( body=Subscript( value=Name(id='l', ctx=Load()), slice=Tuple( elts=[ Slice( lower=Constant(value=1), upper=Constant(value=2)), Constant(value=3)], ctx=Load()), ctx=Load()))
-
class
ast.Slice(lower, upper, step)¶ Обычная нарезка (по форме
lower:upperилиlower:upper:step). Может встречаться только внутри поля slice вSubscript, либо непосредственно, либо как элементTuple.>>> print(ast.dump(ast.parse('l[1:2]', mode='eval'), indent=4)) Expression( body=Subscript( value=Name(id='l', ctx=Load()), slice=Slice( lower=Constant(value=1), upper=Constant(value=2)), ctx=Load()))
Постижения¶
-
class
ast.ListComp(elt, generators)¶ -
class
ast.SetComp(elt, generators)¶ -
class
ast.GeneratorExp(elt, generators)¶ -
class
ast.DictComp(key, value, generators)¶ Понимание списков и множеств, генераторные выражения и понимания словарей.
elt(илиkeyиvalue) - это один узел, представляющий часть, которая будет оцениваться для каждого элемента.generators- это список узловcomprehension.>>> print(ast.dump(ast.parse('[x for x in numbers]', mode='eval'), indent=4)) Expression( body=ListComp( elt=Name(id='x', ctx=Load()), generators=[ comprehension( target=Name(id='x', ctx=Store()), iter=Name(id='numbers', ctx=Load()), ifs=[], is_async=0)])) >>> print(ast.dump(ast.parse('{x: x**2 for x in numbers}', mode='eval'), indent=4)) Expression( body=DictComp( key=Name(id='x', ctx=Load()), value=BinOp( left=Name(id='x', ctx=Load()), op=Pow(), right=Constant(value=2)), generators=[ comprehension( target=Name(id='x', ctx=Store()), iter=Name(id='numbers', ctx=Load()), ifs=[], is_async=0)])) >>> print(ast.dump(ast.parse('{x for x in numbers}', mode='eval'), indent=4)) Expression( body=SetComp( elt=Name(id='x', ctx=Load()), generators=[ comprehension( target=Name(id='x', ctx=Store()), iter=Name(id='numbers', ctx=Load()), ifs=[], is_async=0)]))
-
class
ast.comprehension(target, iter, ifs, is_async)¶ Одно предложение
forв понимании.target- это ссылка, которую следует использовать для каждого элемента - обычно это узелNameилиTuple.iter- это объект для итерации.ifs- это список тестовых выражений: каждый пунктforможет иметь несколькоifs.is_asyncуказывает на асинхронность понимания (использованиеasync forвместоfor). Значение - целое число (0 или 1).>>> print(ast.dump(ast.parse('[ord(c) for line in file for c in line]', mode='eval'), ... indent=4)) # Multiple comprehensions in one. Expression( body=ListComp( elt=Call( func=Name(id='ord', ctx=Load()), args=[ Name(id='c', ctx=Load())], keywords=[]), generators=[ comprehension( target=Name(id='line', ctx=Store()), iter=Name(id='file', ctx=Load()), ifs=[], is_async=0), comprehension( target=Name(id='c', ctx=Store()), iter=Name(id='line', ctx=Load()), ifs=[], is_async=0)])) >>> print(ast.dump(ast.parse('(n**2 for n in it if n>5 if n<10)', mode='eval'), ... indent=4)) # generator comprehension Expression( body=GeneratorExp( elt=BinOp( left=Name(id='n', ctx=Load()), op=Pow(), right=Constant(value=2)), generators=[ comprehension( target=Name(id='n', ctx=Store()), iter=Name(id='it', ctx=Load()), ifs=[ Compare( left=Name(id='n', ctx=Load()), ops=[ Gt()], comparators=[ Constant(value=5)]), Compare( left=Name(id='n', ctx=Load()), ops=[ Lt()], comparators=[ Constant(value=10)])], is_async=0)])) >>> print(ast.dump(ast.parse('[i async for i in soc]', mode='eval'), ... indent=4)) # Async comprehension Expression( body=ListComp( elt=Name(id='i', ctx=Load()), generators=[ comprehension( target=Name(id='i', ctx=Store()), iter=Name(id='soc', ctx=Load()), ifs=[], is_async=1)]))
Заявления¶
-
class
ast.Assign(targets, value, type_comment)¶ Назначение.
targets- это список узлов, аvalue- один узел.Несколько узлов в
targetsпредставляют собой присвоение каждому из них одного и того же значения. Распаковка представлена помещениемTupleилиListвнутриtargets.-
type_comment¶ type_comment- необязательная строка с аннотацией типа в качестве комментария.
>>> print(ast.dump(ast.parse('a = b = 1'), indent=4)) # Multiple assignment Module( body=[ Assign( targets=[ Name(id='a', ctx=Store()), Name(id='b', ctx=Store())], value=Constant(value=1))], type_ignores=[]) >>> print(ast.dump(ast.parse('a,b = c'), indent=4)) # Unpacking Module( body=[ Assign( targets=[ Tuple( elts=[ Name(id='a', ctx=Store()), Name(id='b', ctx=Store())], ctx=Store())], value=Name(id='c', ctx=Load()))], type_ignores=[])
-
-
class
ast.AnnAssign(target, annotation, value, simple)¶ Назначение с аннотацией типа.
target- это один узел, который может бытьName,AttributeилиSubscript.annotation- это аннотация, например, узелConstantилиName.value- это один необязательный узел.simple- булево целое число, установленное в True для узлаNameвtarget, которые не появляются между скобками и, следовательно, являются чистыми именами, а не выражениями.>>> print(ast.dump(ast.parse('c: int'), indent=4)) Module( body=[ AnnAssign( target=Name(id='c', ctx=Store()), annotation=Name(id='int', ctx=Load()), simple=1)], type_ignores=[]) >>> print(ast.dump(ast.parse('(a): int = 1'), indent=4)) # Annotation with parenthesis Module( body=[ AnnAssign( target=Name(id='a', ctx=Store()), annotation=Name(id='int', ctx=Load()), value=Constant(value=1), simple=0)], type_ignores=[]) >>> print(ast.dump(ast.parse('a.b: int'), indent=4)) # Attribute annotation Module( body=[ AnnAssign( target=Attribute( value=Name(id='a', ctx=Load()), attr='b', ctx=Store()), annotation=Name(id='int', ctx=Load()), simple=0)], type_ignores=[]) >>> print(ast.dump(ast.parse('a[1]: int'), indent=4)) # Subscript annotation Module( body=[ AnnAssign( target=Subscript( value=Name(id='a', ctx=Load()), slice=Constant(value=1), ctx=Store()), annotation=Name(id='int', ctx=Load()), simple=0)], type_ignores=[])
-
class
ast.AugAssign(target, op, value)¶ Дополненное присваивание, например
a += 1. В следующем примереtargetявляется узломNameдляx(с контекстомStore),opявляетсяAdd, аvalueявляетсяConstantсо значением 1.Атрибут
targetне может быть классаTupleилиList, в отличие от целейAssign.>>> print(ast.dump(ast.parse('x += 2'), indent=4)) Module( body=[ AugAssign( target=Name(id='x', ctx=Store()), op=Add(), value=Constant(value=2))], type_ignores=[])
-
class
ast.Raise(exc, cause)¶ Оператор
raise.exc- это объект исключения, который должен быть поднят, обычноCallилиName, илиNoneдля отдельногоraise.cause- это необязательная часть дляyвraise x from y.>>> print(ast.dump(ast.parse('raise x from y'), indent=4)) Module( body=[ Raise( exc=Name(id='x', ctx=Load()), cause=Name(id='y', ctx=Load()))], type_ignores=[])
-
class
ast.Assert(test, msg)¶ Утверждение.
testсодержит условие, например, узелCompare.msgсодержит сообщение об отказе.>>> print(ast.dump(ast.parse('assert x,y'), indent=4)) Module( body=[ Assert( test=Name(id='x', ctx=Load()), msg=Name(id='y', ctx=Load()))], type_ignores=[])
-
class
ast.Delete(targets)¶ Представляет собой утверждение
del.targetsпредставляет собой список узлов, таких какName,AttributeилиSubscript.>>> print(ast.dump(ast.parse('del x,y,z'), indent=4)) Module( body=[ Delete( targets=[ Name(id='x', ctx=Del()), Name(id='y', ctx=Del()), Name(id='z', ctx=Del())])], type_ignores=[])
-
class
ast.Pass¶ Оператор
pass.>>> print(ast.dump(ast.parse('pass'), indent=4)) Module( body=[ Pass()], type_ignores=[])
Другие утверждения, которые применимы только внутри функций или циклов, описаны в других разделах.
Импорт¶
-
class
ast.Import(names)¶ Оператор импорта.
names- это список узловalias.>>> print(ast.dump(ast.parse('import x,y,z'), indent=4)) Module( body=[ Import( names=[ alias(name='x'), alias(name='y'), alias(name='z')])], type_ignores=[])
-
class
ast.ImportFrom(module, names, level)¶ Представляет собой
from x import y.module- необработанная строка имени „from“, без ведущих точек, илиNoneдля утверждений типаfrom . import foo.levelпредставляет собой целое число, содержащее уровень относительного импорта (0 означает абсолютный импорт).>>> print(ast.dump(ast.parse('from y import x,y,z'), indent=4)) Module( body=[ ImportFrom( module='y', names=[ alias(name='x'), alias(name='y'), alias(name='z')], level=0)], type_ignores=[])
-
class
ast.alias(name, asname)¶ Оба параметра являются необработанными строками имен.
asnameможет бытьNone, если должно использоваться обычное имя.>>> print(ast.dump(ast.parse('from ..foo.bar import a as b, c'), indent=4)) Module( body=[ ImportFrom( module='foo.bar', names=[ alias(name='a', asname='b'), alias(name='c')], level=2)], type_ignores=[])
Поток управления¶
Примечание
Необязательные условия, такие как else, сохраняются в виде пустого списка, если они отсутствуют.
-
class
ast.If(test, body, orelse)¶ Утверждение
if.testсодержит один узел, например, узелCompare.bodyиorelseсодержат по списку узлов.Клаузы
elifне имеют специального представления в AST, а появляются как дополнительные узлыIfвнутри секцииorelseпредыдущей.>>> print(ast.dump(ast.parse(""" ... if x: ... ... ... elif y: ... ... ... else: ... ... ... """), indent=4)) Module( body=[ If( test=Name(id='x', ctx=Load()), body=[ Expr( value=Constant(value=Ellipsis))], orelse=[ If( test=Name(id='y', ctx=Load()), body=[ Expr( value=Constant(value=Ellipsis))], orelse=[ Expr( value=Constant(value=Ellipsis))])])], type_ignores=[])
-
class
ast.For(target, iter, body, orelse, type_comment)¶ Цикл
for.targetсодержит переменную(ые), которой присваивается цикл, в виде одного узлаName,TupleилиList.iterсодержит элемент, по которому будет выполняться цикл, опять же в виде одного узла.bodyиorelseсодержат списки узлов для выполнения. Узлы вorelseвыполняются, если цикл завершается нормально, а не через операторbreak.-
type_comment¶ type_comment- необязательная строка с аннотацией типа в качестве комментария.
>>> print(ast.dump(ast.parse(""" ... for x in y: ... ... ... else: ... ... ... """), indent=4)) Module( body=[ For( target=Name(id='x', ctx=Store()), iter=Name(id='y', ctx=Load()), body=[ Expr( value=Constant(value=Ellipsis))], orelse=[ Expr( value=Constant(value=Ellipsis))])], type_ignores=[])
-
-
class
ast.While(test, body, orelse)¶ Цикл
while.testсодержит условие, например, узелCompare.>> print(ast.dump(ast.parse(""" ... while x: ... ... ... else: ... ... ... """), indent=4)) Module( body=[ While( test=Name(id='x', ctx=Load()), body=[ Expr( value=Constant(value=Ellipsis))], orelse=[ Expr( value=Constant(value=Ellipsis))])], type_ignores=[])
-
class
ast.Break¶ -
class
ast.Continue¶ Утверждения
breakиcontinue.>>> print(ast.dump(ast.parse("""\ ... for a in b: ... if a > 5: ... break ... else: ... continue ... ... """), indent=4)) Module( body=[ For( target=Name(id='a', ctx=Store()), iter=Name(id='b', ctx=Load()), body=[ If( test=Compare( left=Name(id='a', ctx=Load()), ops=[ Gt()], comparators=[ Constant(value=5)]), body=[ Break()], orelse=[ Continue()])], orelse=[])], type_ignores=[])
-
class
ast.Try(body, handlers, orelse, finalbody)¶ tryблоков. Все атрибуты представляют собой список узлов для выполнения, за исключениемhandlers, который является списком узловExceptHandler.>>> print(ast.dump(ast.parse(""" ... try: ... ... ... except Exception: ... ... ... except OtherException as e: ... ... ... else: ... ... ... finally: ... ... ... """), indent=4)) Module( body=[ Try( body=[ Expr( value=Constant(value=Ellipsis))], handlers=[ ExceptHandler( type=Name(id='Exception', ctx=Load()), body=[ Expr( value=Constant(value=Ellipsis))]), ExceptHandler( type=Name(id='OtherException', ctx=Load()), name='e', body=[ Expr( value=Constant(value=Ellipsis))])], orelse=[ Expr( value=Constant(value=Ellipsis))], finalbody=[ Expr( value=Constant(value=Ellipsis))])], type_ignores=[])
-
class
ast.ExceptHandler(type, name, body)¶ Одиночная оговорка
except.type- это тип исключения, которому оно будет соответствовать, обычно узелName(илиNoneдля всеобъемлющей клаузулыexcept:).name- необработанная строка для имени, в котором будет храниться исключение, илиNone, если в оговорке нетas foo.body- это список узлов.>>> print(ast.dump(ast.parse("""\ ... try: ... a + 1 ... except TypeError: ... pass ... """), indent=4)) Module( body=[ Try( body=[ Expr( value=BinOp( left=Name(id='a', ctx=Load()), op=Add(), right=Constant(value=1)))], handlers=[ ExceptHandler( type=Name(id='TypeError', ctx=Load()), body=[ Pass()])], orelse=[], finalbody=[])], type_ignores=[])
-
class
ast.With(items, body, type_comment)¶ Блок
with.items- это список узловwithitem, представляющих менеджеры контекста, аbody- это блок с отступом внутри контекста.-
type_comment¶ type_comment- необязательная строка с аннотацией типа в качестве комментария.
-
-
class
ast.withitem(context_expr, optional_vars)¶ Одиночный менеджер контекста в блоке
with.context_expr- это менеджер контекста, часто узелCall.optional_vars- этоName,TupleилиListдля частиas foo, илиNone, если она не используется.>>> print(ast.dump(ast.parse("""\ ... with a as b, c as d: ... something(b, d) ... """), indent=4)) Module( body=[ With( items=[ withitem( context_expr=Name(id='a', ctx=Load()), optional_vars=Name(id='b', ctx=Store())), withitem( context_expr=Name(id='c', ctx=Load()), optional_vars=Name(id='d', ctx=Store()))], body=[ Expr( value=Call( func=Name(id='something', ctx=Load()), args=[ Name(id='b', ctx=Load()), Name(id='d', ctx=Load())], keywords=[]))])], type_ignores=[])
Соответствие шаблонов¶
-
class
ast.Match(subject, cases)¶ Утверждение
match.subjectсодержит субъект сопоставления (объект, который сопоставляется со случаями), аcasesсодержит итерацию узловmatch_caseс различными случаями.
-
class
ast.match_case(pattern, guard, body)¶ Одиночный шаблон case в операторе
match.patternсодержит шаблон соответствия, с которым будет сопоставлен объект. Обратите внимание, что узлыAST, создаваемые для шаблонов, отличаются от узлов, создаваемых для выражений, даже если они имеют одинаковый синтаксис.Атрибут
guardсодержит выражение, которое будет оценено, если шаблон соответствует субъекту.bodyсодержит список узлов, которые будут выполняться, если шаблон совпадает и результат оценки защитного выражения равен true.>>> print(ast.dump(ast.parse(""" ... match x: ... case [x] if x>0: ... ... ... case tuple(): ... ... ... """), indent=4)) Module( body=[ Match( subject=Name(id='x', ctx=Load()), cases=[ match_case( pattern=MatchSequence( patterns=[ MatchAs(name='x')]), guard=Compare( left=Name(id='x', ctx=Load()), ops=[ Gt()], comparators=[ Constant(value=0)]), body=[ Expr( value=Constant(value=Ellipsis))]), match_case( pattern=MatchClass( cls=Name(id='tuple', ctx=Load()), patterns=[], kwd_attrs=[], kwd_patterns=[]), body=[ Expr( value=Constant(value=Ellipsis))])])], type_ignores=[])
-
class
ast.MatchValue(value)¶ Литерал соответствия или шаблон значения, который сравнивает по равенству.
valueявляется узлом выражения. Допустимые узлы значений ограничены, как описано в документации по оператору 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- необязательное имя, которое может быть указано для захвата оставшихся элементов отображения. Допустимые ключевые выражения ограничены, как описано в документации по оператору соответствия.Этот шаблон успешный, если объект является отображением, все оцененные ключевые выражения присутствуют в отображении, и значение, соответствующее каждому ключу, соответствует соответствующему подшаблону. Если
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(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)¶ Соответствие «как шаблон», шаблон захвата или шаблон подстановочного знака.
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)¶ Соответствие «или-шаблон». Шаблон «или» поочередно сопоставляет каждый из своих подшаблонов с объектом, пока один из них не окажется успешным. После этого считается, что шаблон «или» достиг успеха. Если ни один из подшаблонов не достиг успеха, то 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))])])], type_ignores=[])
Определения функций и классов¶
-
class
ast.FunctionDef(name, args, body, decorator_list, returns, type_comment)¶ Определение функции.
name- необработанная строка имени функции.argsявляется узломarguments.body- это список узлов внутри функции.decorator_list- это список декораторов, которые будут применены, хранятся сначала крайние (т.е. первый в списке будет применен последним).returns- это аннотация возврата.
-
type_comment¶ type_comment- необязательная строка с аннотацией типа в качестве комментария.
-
class
ast.Lambda(args, body)¶ lambda- это минимальное определение функции, которое может быть использовано внутри выражения. В отличие отFunctionDef,bodyсодержит один узел.>>> print(ast.dump(ast.parse('lambda x,y: ...'), indent=4)) Module( body=[ Expr( value=Lambda( args=arguments( posonlyargs=[], args=[ arg(arg='x'), arg(arg='y')], kwonlyargs=[], kw_defaults=[], defaults=[]), body=Constant(value=Ellipsis)))], type_ignores=[])
-
class
ast.arguments(posonlyargs, args, vararg, kwonlyargs, kw_defaults, kwarg, defaults)¶ Аргументы для функции.
posonlyargs,argsиkwonlyargsявляются списками узловarg.varargиkwargявляются одиночными узламиarg, ссылающимися на параметры*args, **kwargs.kw_defaults- это список значений по умолчанию для аргументов, относящихся только к ключевым словам. Если одно из нихNone, то соответствующий аргумент является обязательным.defaults- это список значений по умолчанию для аргументов, которые могут быть переданы позиционно. Если значений по умолчанию меньше, они соответствуют последним n аргументам.
-
class
ast.arg(arg, annotation, type_comment)¶ Одиночный аргумент в списке.
arg- необработанная строка имени аргумента,annotation- его аннотация, например, узелStrилиName.-
type_comment¶ type_comment- необязательная строка с аннотацией типа в качестве комментария
>>> print(ast.dump(ast.parse("""\ ... @decorator1 ... @decorator2 ... def f(a: 'annotation', b=1, c=2, *d, e, f=3, **g) -> 'return annotation': ... pass ... """), indent=4)) Module( body=[ FunctionDef( name='f', args=arguments( posonlyargs=[], args=[ arg( arg='a', annotation=Constant(value='annotation')), arg(arg='b'), arg(arg='c')], vararg=arg(arg='d'), kwonlyargs=[ arg(arg='e'), arg(arg='f')], kw_defaults=[ None, Constant(value=3)], kwarg=arg(arg='g'), defaults=[ Constant(value=1), Constant(value=2)]), body=[ Pass()], decorator_list=[ Name(id='decorator1', ctx=Load()), Name(id='decorator2', ctx=Load())], returns=Constant(value='return annotation'))], type_ignores=[])
-
-
class
ast.Return(value)¶ Оператор
return.>>> print(ast.dump(ast.parse('return 4'), indent=4)) Module( body=[ Return( value=Constant(value=4))], type_ignores=[])
-
class
ast.Yield(value)¶ -
class
ast.YieldFrom(value)¶ Выражение
yieldилиyield from. Поскольку это выражения, они должны быть обернуты в узелExpr, если отправленное обратно значение не используется.>>> print(ast.dump(ast.parse('yield x'), indent=4)) Module( body=[ Expr( value=Yield( value=Name(id='x', ctx=Load())))], type_ignores=[]) >>> print(ast.dump(ast.parse('yield from x'), indent=4)) Module( body=[ Expr( value=YieldFrom( value=Name(id='x', ctx=Load())))], type_ignores=[])
-
class
ast.Global(names)¶ -
class
ast.Nonlocal(names)¶ globalиnonlocalутверждения.namesпредставляет собой список необработанных строк.>>> print(ast.dump(ast.parse('global x,y,z'), indent=4)) Module( body=[ Global( names=[ 'x', 'y', 'z'])], type_ignores=[]) >>> print(ast.dump(ast.parse('nonlocal x,y,z'), indent=4)) Module( body=[ Nonlocal( names=[ 'x', 'y', 'z'])], type_ignores=[])
-
class
ast.ClassDef(name, bases, keywords, starargs, kwargs, body, decorator_list)¶ Определение класса.
name- необработанная строка для имени классаbases- это список узлов для явно указанных базовых классов.keywordsпредставляет собой список узловkeyword, в основном для „metaclass“. Другие ключевые слова будут переданы в метакласс в соответствии с PEP-3115.starargsиkwargs- это каждый отдельный узел, как в вызове функции. starargs будет расширен для присоединения к списку базовых классов, а kwargs будет передан метаклассу.body- это список узлов, представляющих код внутри определения класса.decorator_list- это список узлов, как вFunctionDef.
>>> print(ast.dump(ast.parse("""\ ... @decorator1 ... @decorator2 ... class Foo(base1, base2, metaclass=meta): ... pass ... """), indent=4)) Module( body=[ ClassDef( name='Foo', bases=[ Name(id='base1', ctx=Load()), Name(id='base2', ctx=Load())], keywords=[ keyword( arg='metaclass', value=Name(id='meta', ctx=Load()))], body=[ Pass()], decorator_list=[ Name(id='decorator1', ctx=Load()), Name(id='decorator2', ctx=Load())])], type_ignores=[])
Асинхронность и ожидание¶
-
class
ast.AsyncFunctionDef(name, args, body, decorator_list, returns, type_comment)¶ Определение функции
async def. Имеет те же поля, что иFunctionDef.
-
class
ast.Await(value)¶ Выражение
await.value- это то, чего оно ожидает. Действителен только в теле выраженияAsyncFunctionDef.
>>> print(ast.dump(ast.parse("""\
... async def f():
... await other_func()
... """), indent=4))
Module(
body=[
AsyncFunctionDef(
name='f',
args=arguments(
posonlyargs=[],
args=[],
kwonlyargs=[],
kw_defaults=[],
defaults=[]),
body=[
Expr(
value=Await(
value=Call(
func=Name(id='other_func', ctx=Load()),
args=[],
keywords=[])))],
decorator_list=[])],
type_ignores=[])
-
class
ast.AsyncFor(target, iter, body, orelse, type_comment)¶ -
class
ast.AsyncWith(items, body, type_comment)¶ async forциклы иasync withконтекстные менеджеры. Они имеют те же поля, что иForиWithсоответственно. Действительны только в телеAsyncFunctionDef.
Примечание
Когда строка разбирается с помощью ast.parse(), операторные узлы (подклассы ast.operator, ast.unaryop, ast.cmpop, ast.boolop и ast.expr_context) на возвращаемом дереве будут синглтонами. Изменения в одном из них будут отражены во всех остальных вхождениях того же значения (например, ast.Add).
ast Помощники¶
Помимо классов узлов, модуль ast определяет эти служебные функции и классы для обхода абстрактных синтаксических деревьев:
-
ast.parse(source, filename='<unknown>', mode='exec', *, type_comments=False, feature_version=None)¶ Разобрать источник в узел AST. Эквивалентно
compile(source, filename, mode, ast.PyCF_ONLY_AST).Если указано
type_comments=True, синтаксический анализатор модифицируется для проверки и возврата комментариев типов, указанных PEP 484 и PEP 526. Это эквивалентно добавлениюast.PyCF_TYPE_COMMENTSк флагам, переданным вcompile(). Это сообщит о синтаксических ошибках для неправильно размещенных комментариев типов. Без этого флага комментарии типов будут игнорироваться, а полеtype_commentв выбранных узлах AST всегда будетNone. Кроме того, расположение комментариев# type: ignoreбудет возвращаться в виде атрибутаtype_ignoresвModule(иначе это всегда пустой список).Кроме того, если
modeявляется'func_type', входной синтаксис модифицируется, чтобы соответствовать PEP 484 «комментариям типа сигнатуры», например,(str, int) -> List[str].Кроме того, установка
feature_versionв кортеж(major, minor)приведет к попытке разбора с использованием грамматики этой версии Python. В настоящее времяmajorдолжно быть равно3. Например, установкаfeature_version=(3, 4)позволит использоватьasyncиawaitв качестве имен переменных. Наименьшая поддерживаемая версия -(3, 4); наибольшая -sys.version_info[0:2].Если источник содержит нулевой символ (“0“), выдается сообщение
ValueError.Предупреждение
Обратите внимание, что успешный разбор исходного кода в объект AST не гарантирует, что предоставленный исходный код является корректным кодом Python, который может быть выполнен, так как на этапе компиляции могут возникнуть дополнительные исключения
SyntaxError. Например, источникreturn 42генерирует корректный узел AST для оператора return, но он не может быть скомпилирован сам по себе (он должен находиться внутри узла функции).В частности,
ast.parse()не будет выполнять никаких проверок масштабирования, что делает шаг компиляции.Предупреждение
Возможно аварийное завершение работы интерпретатора Python с достаточно большой/сложной строкой из-за ограничений глубины стека в AST-компиляторе Python.
Изменено в версии 3.8: Добавлены
type_comments,mode='func_type'иfeature_version.
-
ast.unparse(ast_obj)¶ Разберите объект
ast.ASTи сгенерируйте строку с кодом, который произведет эквивалентный объектast.AST, если его разобрать обратно с помощьюast.parse().Предупреждение
Произведенная строка кода не обязательно будет равна исходному коду, который сгенерировал объект
ast.AST(без каких-либо оптимизаций компилятора, таких как константные кортежи/розетки).Предупреждение
Попытка разобрать очень сложное выражение приведет к результату
RecursionError.Добавлено в версии 3.9.
-
ast.literal_eval(node_or_string)¶ Безопасная оценка узла выражения или строки, содержащей литерал Python или контейнерное отображение. Предоставленная строка или узел могут состоять только из следующих буквенных структур Python: строки, байты, числа, кортежи, списки, dicts, множества, булевы,
NoneиEllipsis.Это можно использовать для безопасной оценки строк, содержащих значения Python из ненадежных источников без необходимости самостоятельно разбирать значения. Он не способен оценивать произвольно сложные выражения, например, с операторами или индексацией.
Предупреждение
Возможно аварийное завершение работы интерпретатора Python с достаточно большой/сложной строкой из-за ограничений глубины стека в AST-компиляторе Python.
В зависимости от искаженного ввода он может вызвать
ValueError,TypeError,SyntaxError,MemoryErrorиRecursionError.Изменено в версии 3.2: Теперь позволяет использовать байты и литералы множеств.
Изменено в версии 3.9: Теперь поддерживается создание пустых множеств с помощью
'set()'.Изменено в версии 3.10: При вводе строк ведущие пробелы и табуляции теперь удаляются.
-
ast.get_docstring(node, clean=True)¶ Возвращает docstring данного node (который должен быть узлом
FunctionDef,AsyncFunctionDef,ClassDefилиModule), илиNone, если он не имеет docstring. Если clean равно true, очистите отступы doc-строки с помощьюinspect.cleandoc().Изменено в версии 3.5:
AsyncFunctionDefтеперь поддерживается.
-
ast.get_source_segment(source, node, *, padded=False)¶ Получить сегмент исходного кода источника, который породил узел. Если некоторая информация о местоположении (
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, которое присутствует на узле.
-
ast.iter_child_nodes(node)¶ Выдает все прямые дочерние узлы node, то есть все поля, которые являются узлами, и все элементы полей, которые являются списками узлов.
-
ast.walk(node)¶ Рекурсивно выдает все узлы-потомки в дереве, начиная с node (включая сам node), без определенного порядка. Это полезно, если вы хотите изменять узлы только на месте и не заботитесь о контексте.
-
class
ast.NodeVisitor¶ Базовый класс посетителя узлов, который обходит абстрактное дерево синтаксиса и вызывает функцию посетителя для каждого найденного узла. Эта функция может возвращать значение, которое передается методом
visit().Этот класс предназначен для создания подклассов, при этом подкласс добавляет методы посетителей.
-
visit(node)¶ Посетить узел. Реализация по умолчанию вызывает метод
self.visit_classname, где classname - имя класса узла, илиgeneric_visit(), если такого метода не существует.
-
generic_visit(node)¶ Этот посетитель вызывает
visit()на всех дочерних узлах узла.Обратите внимание, что дочерние узлы узлов, имеющих пользовательский метод посетителя, не будут посещены, пока посетитель не вызовет
generic_visit()или не посетит их сам.
Не используйте
NodeVisitor, если вы хотите вносить изменения в узлы во время обхода. Для этого существует специальный посетитель (NodeTransformer), который позволяет вносить изменения.Не рекомендуется, начиная с версии 3.8: Методы
visit_Num(),visit_Str(),visit_Bytes(),visit_NameConstant()иvisit_Ellipsis()теперь устарели и не будут вызываться в будущих версиях Python. Добавьте методvisit_Constant()для обработки всех константных узлов.-
-
class
ast.NodeTransformer¶ Подкласс
NodeVisitor, который обходит дерево абстрактного синтаксиса и позволяет модифицировать узлы.NodeTransformerпройдет по AST и использует возвращаемое значение методов посетителей для замены или удаления старого узла. Если возвращаемое значение метода посетителя равноNone, узел будет удален из своего местоположения, в противном случае он будет заменен возвращаемым значением. Возвращаемое значение может быть исходным узлом, в этом случае замена не происходит.Вот пример трансформатора, который переписывает все вхождения поиска имени (
foo) вdata['foo']:class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load()), slice=Constant(value=node.id), ctx=node.ctx )
Помните, что если узел, с которым вы работаете, имеет дочерние узлы, вы должны либо преобразовать дочерние узлы самостоятельно, либо сначала вызвать метод
generic_visit()для узла.Для узлов, которые были частью коллекции утверждений (это относится ко всем узлам утверждений), посетитель может также вернуть список узлов, а не только один узел.
Если
NodeTransformerвводит новые узлы (которые не были частью исходного дерева) без предоставления им информации о расположении (например,lineno),fix_missing_locations()должен быть вызван с новым поддеревом для пересчета информации о расположении:tree = ast.parse('foo', mode='eval') new_tree = fix_missing_locations(RewriteName().visit(tree))
Обычно вы используете трансформатор следующим образом:
node = YourTransformer().visit(node)
-
ast.dump(node, annotate_fields=True, include_attributes=False, *, indent=None)¶ Возвращает форматированный дамп дерева в node. Это в основном полезно для отладки. Если annotate_fields равно true (по умолчанию), в возвращаемой строке будут показаны имена и значения полей. Если annotate_fields равно false, результирующая строка будет более компактной за счет исключения однозначных имен полей. Такие атрибуты, как номера строк и смещения столбцов, по умолчанию не передаются в дамп. Если это необходимо, include_attributes можно установить в true.
Если indent - неотрицательное целое число или строка, то дерево будет напечатано с этим уровнем отступа. Уровень отступа 0, отрицательный, или
""будет вставлять только новые строки.None(по умолчанию) выбирает однострочное представление. При использовании целого положительного числа отступ отступает на столько-то пробелов за уровень. Если indent является строкой (например,"\t"), то эта строка используется для отступа на каждом уровне.Изменено в версии 3.9: Добавлена опция indent.
Флаги компилятора¶
Следующие флаги могут быть переданы в compile() для изменения влияния на компиляцию программы:
-
ast.PyCF_ALLOW_TOP_LEVEL_AWAIT¶ Включает поддержку верхнего уровня
await,async for,async withи асинхронных пониманий.Добавлено в версии 3.8.
-
ast.PyCF_ONLY_AST¶ Генерирует и возвращает абстрактное дерево синтаксиса вместо того, чтобы возвращать объект скомпилированного кода.
Использование командной строки¶
Добавлено в версии 3.9.
Модуль ast может быть выполнен как сценарий из командной строки. Это очень просто:
python -m ast [-m <mode>] [-a] [infile]
Принимаются следующие варианты:
-
-h,--help¶ Покажите сообщение справки и выйдите.
-
-m<mode>¶ -
--mode<mode>¶ Укажите, какой тип кода должен быть скомпилирован, подобно аргументу mode в
parse().
-
--no-type-comments¶ Не разбирайте комментарии типа.
-
-a,--include-attributes¶ Включите такие атрибуты, как номера строк и смещения колонок.
Если указано infile, его содержимое разбирается на AST и выводится на stdout. В противном случае содержимое считывается из stdin.
См.также
Green Tree Snakes, внешний ресурс документации, содержит хорошие подробности о работе с АСТ Python.
ASTTokens аннотирует АСТ Python с указанием позиций лексем и текста в исходном коде, который их породил. Это полезно для инструментов, которые выполняют преобразования исходного кода.
leoAst.py объединяет представления программ на основе лексем и деревьев разбора python, вставляя двусторонние связи между лексемами и узлами ast.
LibCST разбирает код в виде конкретного синтаксического дерева, которое выглядит как дерево ast и сохраняет все детали форматирования. Это полезно для создания приложений автоматического рефакторинга (codemod) и линтеров.
Parso - это парсер Python, который поддерживает восстановление ошибок и парсинг по кругу для различных версий Python (в нескольких версиях Python). Parso также способен перечислить множество синтаксических ошибок в вашем файле python.