ast — 抽象语法树¶
源代码: Lib/ast.py
The ast 模块帮助 Python 应用程序处理 Python 抽象语法树。抽象语法本身可能在每个 Python 版本中都会发生变化;此模块有助于以编程方式找出当前语法的结构。
抽象语法树可以通过将 ast.PyCF_ONLY_AST 作为标志传递给 compile() 内置函数,或使用此模块中提供的 parse() 助手来生成。结果将是一个对象树,其类都继承自 ast.AST。抽象语法树可以使用内置的 compile() 函数编译成 Python 代码对象。
抽象语法¶
抽象语法目前定义如下
-- 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)
| ParamSpec(identifier name)
| TypeVarTuple(identifier name)
attributes (int lineno, int col_offset, int end_lineno, int end_col_offset)
}
节点类¶
- class ast.AST¶
这是所有 AST 节点类的基类。实际的节点类是从
Parser/Python.asdl文件派生的,该文件在 上面 进行了复制。它们在_astC 模块中定义,并在ast中重新导出。抽象语法中的每个左侧符号都定义了一个类(例如,
ast.stmt或ast.expr)。此外,右侧的每个构造函数都定义了一个类;这些类继承自左侧树的类。例如,ast.BinOp继承自ast.expr。对于具有备选方案(也称为“总和”)的生成规则,左侧类是抽象的:永远只创建特定构造函数节点的实例。- _fields¶
每个具体类都有一个属性
_fields,它给出所有子节点的名称。每个具体类的实例都为每个子节点有一个属性,其类型与语法中定义的类型相同。例如,
ast.BinOp实例有一个类型为ast.expr的属性left。如果这些属性在语法中被标记为可选(使用问号),则该值可能是
None。如果属性可以具有零个或多个值(用星号标记),则这些值将表示为 Python 列表。在使用compile()编译 AST 时,所有可能的属性都必须存在并具有有效值。
- lineno¶
- col_offset¶
- end_lineno¶
- end_col_offset¶
ast.expr和ast.stmt子类的实例具有lineno、col_offset、end_lineno和end_col_offset属性。Thelineno和end_lineno是源文本跨度的第一个和最后一个行号(从 1 开始索引,因此第一行是第 1 行),而col_offset和end_col_offset是生成该节点的第一个和最后一个标记的相应 UTF-8 字节偏移量。UTF-8 偏移量被记录下来,因为解析器在内部使用 UTF-8。请注意,编译器不需要结束位置,因此它们是可选的。结束偏移量位于最后一个符号之后,例如,可以使用
source_line[node.col_offset : node.end_col_offset]获取单行表达式节点的源段。
类
ast.T的构造函数按如下方式解析其参数如果有位置参数,则必须与
T._fields中的项目数量相同;它们将被分配为这些名称的属性。如果有关键字参数,它们将设置相同名称的属性为给定的值。
例如,要创建和填充一个
ast.UnaryOp节点,可以使用node = ast.UnaryOp() node.op = ast.USub() node.operand = ast.Constant() node.operand.value = 5 node.operand.lineno = 0 node.operand.col_offset = 0 node.lineno = 0 node.col_offset = 0
或者更紧凑的
node = ast.UnaryOp(ast.USub(), ast.Constant(5, lineno=0, col_offset=0), lineno=0, col_offset=0)
在版本 3.8 中更改: 类 ast.Constant 现在用于所有常量。
在版本 3.9 中更改: 简单索引由其值表示,扩展切片由元组表示。
自版本 3.8 起弃用: 旧类 ast.Num、ast.Str、ast.Bytes、ast.NameConstant 和 ast.Ellipsis 仍然可用,但将在未来的 Python 版本中删除。在此期间,实例化它们将返回一个不同类的实例。
自版本 3.9 起弃用: 旧类 ast.Index 和 ast.ExtSlice 仍然可用,但将在未来的 Python 版本中删除。在此期间,实例化它们将返回一个不同类的实例。
注意
此处显示的特定节点类的描述最初改编自出色的 Green Tree Snakes 项目及其所有贡献者。
根节点¶
- class ast.Module(body, type_ignores)¶
一个 Python 模块,与 文件输入 相同。在默认的
"exec"模式中,由ast.parse()生成的节点类型。type_ignores 是模块类型忽略注释的
list;有关更多详细信息,请参见ast.parse()。>>> print(ast.dump(ast.parse('x = 1'), indent=4)) Module( body=[ Assign( targets=[ Name(id='x', ctx=Store())], value=Constant(value=1))], type_ignores=[])
- class ast.Expression(body)¶
单个 Python 表达式输入。当 mode 为
"eval"时,由ast.parse()生成的节点类型。body 是单个节点,是 表达式类型 之一。
>>> print(ast.dump(ast.parse('123', mode='eval'), indent=4)) Expression( body=Constant(value=123))
- class ast.Interactive(body)¶
单个 交互式输入,如 交互模式。当 mode 为
"single"时,由ast.parse()生成的节点类型。>>> 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)¶
旧式函数类型注释的表示,因为 3.5 之前的 Python 版本不支持 PEP 484 注释。当 mode 为
"func_type"时,由ast.parse()生成的节点类型。此类类型注释将如下所示
def sum_two_number(a, b): # type: (int, int) -> int return a + b
returns 是单个 表达式节点。
>>> print(ast.dump(ast.parse('(int, str) -> List[int]', mode='func_type'), indent=4)) FunctionType( argtypes=[ Name(id='int', ctx=Load()), Name(id='str', ctx=Load())], returns=Subscript( value=Name(id='List', ctx=Load()), slice=Name(id='int', ctx=Load()), ctx=Load()))
在 3.8 版本中添加。
字面量¶
- class ast.Constant(value)¶
常量值。
Constant字面量的value属性包含它所表示的 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-string 中单个格式化字段的节点。如果字符串包含单个格式化字段且没有其他内容,则该节点可以被隔离,否则它将出现在
JoinedStr中。value是任何表达式节点(例如字面量、变量或函数调用)。conversion是一个整数-1:无格式化
115:
!s字符串格式化114:
!rrepr 格式化97:
!aascii 格式化
format_spec是一个JoinedStr节点,表示值的格式,如果未指定格式,则为None。conversion和format_spec可以同时设置。
- class ast.JoinedStr(values)¶
一个 f-string,包含一系列
FormattedValue和Constant节点。>>> print(ast.dump(ast.parse('f"sin({a}) is {sin(a):.3}"', mode='eval'), indent=4)) Expression( body=JoinedStr( values=[ Constant(value='sin('), FormattedValue( value=Name(id='a', ctx=Load()), conversion=-1), Constant(value=') is '), FormattedValue( value=Call( func=Name(id='sin', ctx=Load()), args=[ Name(id='a', ctx=Load())], keywords=[]), conversion=-1, format_spec=JoinedStr( values=[ Constant(value='.3')]))]))
- class ast.List(elts, ctx)¶
- class ast.Tuple(elts, ctx)¶
列表或元组。
elts保存表示元素的节点列表。ctx是Store,如果容器是赋值目标(即(x,y)=something),否则是Load。>>> print(ast.dump(ast.parse('[1, 2, 3]', mode='eval'), indent=4)) Expression( body=List( elts=[ Constant(value=1), Constant(value=2), Constant(value=3)], ctx=Load())) >>> print(ast.dump(ast.parse('(1, 2, 3)', mode='eval'), indent=4)) Expression( body=Tuple( elts=[ Constant(value=1), Constant(value=2), Constant(value=3)], ctx=Load()))
- class ast.Set(elts)¶
一个集合。
elts保存表示集合元素的节点列表。>>> print(ast.dump(ast.parse('{1, 2, 3}', mode='eval'), indent=4)) Expression( body=Set( elts=[ Constant(value=1), Constant(value=2), Constant(value=3)]))
- class ast.Dict(keys, values)¶
一个字典。
keys和values保存表示键和值的节点列表,顺序匹配(调用dictionary.keys()和dictionary.values()时将返回的内容)。使用字典字面量进行字典解包时,要扩展的表达式将进入
values列表,并在keys中的相应位置使用None。>>> print(ast.dump(ast.parse('{"a":1, **d}', mode='eval'), indent=4)) Expression( body=Dict( keys=[ Constant(value='a'), None], values=[ Constant(value=1), Name(id='d', ctx=Load())]))
变量¶
- class ast.Name(id, ctx)¶
变量名。
id存储名称作为字符串,而ctx是以下类型之一。
- class ast.Load¶
- class ast.Store¶
- class ast.Del¶
变量引用可用于加载变量的值,为其分配新值或将其删除。 变量引用被赋予一个上下文以区分这些情况。
>>> print(ast.dump(ast.parse('a'), indent=4)) Module( body=[ Expr( value=Name(id='a', ctx=Load()))], type_ignores=[]) >>> print(ast.dump(ast.parse('a = 1'), indent=4)) Module( body=[ Assign( targets=[ Name(id='a', ctx=Store())], value=Constant(value=1))], type_ignores=[]) >>> print(ast.dump(ast.parse('del a'), indent=4)) Module( body=[ Delete( targets=[ Name(id='a', ctx=Del())])], type_ignores=[])
- class ast.Starred(value, ctx)¶
一个
*var变量引用。value保存变量,通常是一个Name节点。 当构建具有*args的Call节点时,必须使用此类型。>>> 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)¶
函数调用。
func是函数,通常是Name或Attribute对象。参数args包含按位置传递的参数列表。keywords包含keyword对象列表,表示按关键字传递的参数。
创建
Call节点时,args和keywords是必需的,但它们可以是空列表。>>> print(ast.dump(ast.parse('func(a, b=c, *d, **e)', mode='eval'), indent=4)) Expression( body=Call( func=Name(id='func', ctx=Load()), args=[ Name(id='a', ctx=Load()), Starred( value=Name(id='d', ctx=Load()), ctx=Load())], keywords=[ keyword( arg='b', value=Name(id='c', ctx=Load())), keyword( value=Name(id='e', ctx=Load()))]))
- class ast.keyword(arg, value)¶
函数调用或类定义的关键字参数。
arg是参数名称的原始字符串,value是要传入的节点。
- class ast.IfExp(test, body, orelse)¶
表达式,例如
a if b else c。每个字段都包含一个节点,因此在以下示例中,所有三个字段都是Name节点。>>> print(ast.dump(ast.parse('a if b else c', mode='eval'), indent=4)) Expression( body=IfExp( test=Name(id='b', ctx=Load()), body=Name(id='a', ctx=Load()), orelse=Name(id='c', ctx=Load())))
- class ast.Attribute(value, attr, ctx)¶
属性访问,例如
d.keys。value是一个节点,通常是一个Name。attr是一个裸字符串,给出属性的名称,ctx是Load、Store或Del,具体取决于对属性的操作方式。>>> print(ast.dump(ast.parse('snake.colour', mode='eval'), indent=4)) Expression( body=Attribute( value=Name(id='snake', ctx=Load()), attr='colour', ctx=Load()))
- class ast.NamedExpr(target, value)¶
命名表达式。此 AST 节点由赋值表达式运算符(也称为海豹运算符)生成。与
Assign节点不同,在该节点中,第一个参数可以是多个节点,在本例中,target和value都必须是单个节点。>>> print(ast.dump(ast.parse('(x := 4)', mode='eval'), indent=4)) Expression( body=NamedExpr( target=Name(id='x', ctx=Store()), value=Constant(value=4)))
在 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的形式)。只能出现在Subscript的 slice 字段中,可以直接出现,也可以作为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始终为 0(表示“复杂”目标)或 1(表示“简单”目标)。“简单”目标仅包含一个Name节点,该节点不会出现在括号之间;所有其他目标都被视为复杂目标。只有简单目标会出现在模块和类的__annotations__字典中。>>> 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是x的Name节点(带有Store上下文),op是Add,而value是一个值为 1 的Constant。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,或者对于独立的raise则是None。cause是raise x from y中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.TypeAlias(name, type_params, value)¶
通过 类型别名 创建的
type语句。name是别名的名称,type_params是 类型参数 的列表,value是类型别名的值。>>> print(ast.dump(ast.parse('type Alias = int'), indent=4)) Module( body=[ TypeAlias( name=Name(id='Alias', ctx=Store()), type_params=[], value=Name(id='int', ctx=Load()))], type_ignores=[])
在 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')])], type_ignores=[])
- class ast.ImportFrom(module, names, level)¶
表示
from x import y。module是 “from” 名称的原始字符串,不包含任何前导点,或对于from . import foo这样的语句,则为None。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 中没有特殊表示,而是作为前一个子句的orelse部分中的额外If节点出现。>>> 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、Attribute或Subscript节点。iter包含要循环遍历的项目,同样作为单个节点。body和orelse包含要执行的节点列表。如果循环正常结束,而不是通过break语句结束,则执行orelse中的节点。- type_comment¶
type_comment是一个可选的字符串,包含类型注释作为注释。
>>> print(ast.dump(ast.parse(""" ... for x in y: ... ... ... else: ... ... ... """), indent=4)) Module( body=[ For( target=Name(id='x', ctx=Store()), iter=Name(id='y', ctx=Load()), body=[ Expr( value=Constant(value=Ellipsis))], orelse=[ Expr( value=Constant(value=Ellipsis))])], type_ignores=[])
- class ast.While(test, body, orelse)¶
一个
while循环。test包含条件,例如Compare节点。>> print(ast.dump(ast.parse(""" ... while x: ... ... ... else: ... ... ... """), indent=4)) Module( body=[ While( test=Name(id='x', ctx=Load()), body=[ Expr( value=Constant(value=Ellipsis))], orelse=[ Expr( value=Constant(value=Ellipsis))])], type_ignores=[])
- class ast.Break¶
- class ast.Continue¶
break和continue语句。>>> print(ast.dump(ast.parse("""\ ... for a in b: ... if a > 5: ... break ... else: ... continue ... ... """), indent=4)) Module( body=[ For( target=Name(id='a', ctx=Store()), iter=Name(id='b', ctx=Load()), body=[ If( test=Compare( left=Name(id='a', ctx=Load()), ops=[ Gt()], comparators=[ Constant(value=5)]), body=[ Break()], orelse=[ Continue()])], orelse=[])], type_ignores=[])
- class ast.Try(body, handlers, orelse, finalbody)¶
try块。所有属性都是要执行的节点列表,除了handlers,它是一个ExceptHandler节点的列表。>>> print(ast.dump(ast.parse(""" ... try: ... ... ... except Exception: ... ... ... except OtherException as e: ... ... ... else: ... ... ... finally: ... ... ... """), indent=4)) Module( body=[ Try( body=[ Expr( value=Constant(value=Ellipsis))], handlers=[ ExceptHandler( type=Name(id='Exception', ctx=Load()), body=[ Expr( value=Constant(value=Ellipsis))]), ExceptHandler( type=Name(id='OtherException', ctx=Load()), name='e', body=[ Expr( value=Constant(value=Ellipsis))])], orelse=[ Expr( value=Constant(value=Ellipsis))], finalbody=[ Expr( value=Constant(value=Ellipsis))])], type_ignores=[])
- class ast.TryStar(body, handlers, orelse, finalbody)¶
后面跟着
except*子句的try块。属性与Try相同,但handlers中的ExceptHandler节点被解释为except*块,而不是except。>>> print(ast.dump(ast.parse(""" ... try: ... ... ... except* Exception: ... ... ... """), indent=4)) Module( body=[ TryStar( body=[ Expr( value=Constant(value=Ellipsis))], handlers=[ ExceptHandler( type=Name(id='Exception', ctx=Load()), body=[ Expr( value=Constant(value=Ellipsis))])], orelse=[], finalbody=[])], type_ignores=[])
在 3.11 版本中添加。
- class ast.ExceptHandler(type, name, body)¶
单个
except子句。type是它将匹配的异常类型,通常是Name节点(或用于捕获所有异常的except:子句的None)。name是用于保存异常的名称的原始字符串,如果子句没有as foo,则为None。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节点可迭代对象,包含不同的案例。在版本 3.10 中添加。
- class ast.match_case(pattern, guard, body)¶
一个
match语句中的单个案例模式。pattern包含主题将与之匹配的匹配模式。请注意,为模式生成的AST节点与为表达式生成的节点不同,即使它们共享相同的语法。如果模式与主题匹配,则
guard属性包含一个将被评估的表达式。body包含一个节点列表,如果模式匹配并且评估保护表达式结果为真,则执行这些节点。>>> print(ast.dump(ast.parse(""" ... match x: ... case [x] if x>0: ... ... ... case tuple(): ... ... ... """), indent=4)) Module( body=[ Match( subject=Name(id='x', ctx=Load()), cases=[ match_case( pattern=MatchSequence( patterns=[ MatchAs(name='x')]), guard=Compare( left=Name(id='x', ctx=Load()), ops=[ Gt()], comparators=[ Constant(value=0)]), body=[ Expr( value=Constant(value=Ellipsis))]), match_case( pattern=MatchClass( cls=Name(id='tuple', ctx=Load()), patterns=[], kwd_attrs=[], kwd_patterns=[]), body=[ Expr( value=Constant(value=Ellipsis))])])], type_ignores=[])
在版本 3.10 中添加。
- class ast.MatchValue(value)¶
一个通过相等比较的匹配文字或值模式。
value是一个表达式节点。允许的值节点在匹配语句文档中有所限制。如果匹配主题等于评估的值,则此模式成功。>>> print(ast.dump(ast.parse(""" ... match x: ... case "Relevant": ... ... ... """), indent=4)) Module( body=[ Match( subject=Name(id='x', ctx=Load()), cases=[ match_case( pattern=MatchValue( value=Constant(value='Relevant')), body=[ Expr( value=Constant(value=Ellipsis))])])], type_ignores=[])
在版本 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))])])], type_ignores=[])
在版本 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))])])], type_ignores=[])
在版本 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))])])], type_ignores=[])
在版本 3.10 中添加。
- class ast.MatchMapping(keys, patterns, rest)¶
一个匹配映射模式。
keys是表达式节点的序列。patterns是相应的模式节点序列。rest是一个可选名称,可以指定它来捕获剩余的映射元素。允许的键表达式在匹配语句文档中有所限制。如果主题是映射,所有评估的键表达式都存在于映射中,并且与每个键相对应的值与相应的子模式匹配,则此模式成功。如果
rest不是None,则如果总体映射模式成功,则将包含剩余映射元素的字典绑定到该名称。>>> print(ast.dump(ast.parse(""" ... match x: ... case {1: _, 2: _}: ... ... ... case {**rest}: ... ... ... """), indent=4)) Module( body=[ Match( subject=Name(id='x', ctx=Load()), cases=[ match_case( pattern=MatchMapping( keys=[ Constant(value=1), Constant(value=2)], patterns=[ MatchAs(), MatchAs()]), body=[ Expr( value=Constant(value=Ellipsis))]), match_case( pattern=MatchMapping(keys=[], patterns=[], rest='rest'), body=[ Expr( value=Constant(value=Ellipsis))])])], type_ignores=[])
在版本 3.10 中添加。
- class ast.MatchClass(cls, patterns, kwd_attrs, kwd_patterns)¶
一个匹配类模式。
cls是一个表达式,给出要匹配的名义类。patterns是一个模式节点序列,要与为类定义的模式匹配属性序列匹配。kwd_attrs是一个要匹配的附加属性序列(在类模式中指定为关键字参数),kwd_patterns是相应的模式(在类模式中指定为关键字值)。如果主题是提名类的实例,所有位置模式都与相应的类定义属性匹配,并且任何指定的关键字属性都与其相应的模式匹配,则此模式成功。
注意:类可以定义一个返回 self 的属性,以便将模式节点与正在匹配的实例匹配。几个内置类型也以这种方式匹配,如匹配语句文档中所述。
>>> print(ast.dump(ast.parse(""" ... match x: ... case Point2D(0, 0): ... ... ... case Point3D(x=0, y=0, z=0): ... ... ... """), indent=4)) Module( body=[ Match( subject=Name(id='x', ctx=Load()), cases=[ match_case( pattern=MatchClass( cls=Name(id='Point2D', ctx=Load()), patterns=[ MatchValue( value=Constant(value=0)), MatchValue( value=Constant(value=0))], kwd_attrs=[], kwd_patterns=[]), body=[ Expr( value=Constant(value=Ellipsis))]), match_case( pattern=MatchClass( cls=Name(id='Point3D', ctx=Load()), patterns=[], kwd_attrs=[ 'x', 'y', 'z'], kwd_patterns=[ MatchValue( value=Constant(value=0)), MatchValue( value=Constant(value=0)), MatchValue( value=Constant(value=0))]), body=[ Expr( value=Constant(value=Ellipsis))])])], type_ignores=[])
在版本 3.10 中添加。
- class ast.MatchAs(pattern, name)¶
一个匹配“as-pattern”、捕获模式或通配符模式。
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=[])
在版本 3.10 中添加。
- class ast.MatchOr(patterns)¶
匹配“或模式”。或模式依次将每个子模式与主题匹配,直到其中一个成功。然后,或模式被认为成功。如果所有子模式均未成功,则或模式失败。
patterns属性包含一个匹配模式节点列表,这些节点将与主题匹配。>>> print(ast.dump(ast.parse(""" ... match x: ... case [x] | (y): ... ... ... """), indent=4)) Module( body=[ Match( subject=Name(id='x', ctx=Load()), cases=[ match_case( pattern=MatchOr( patterns=[ MatchSequence( patterns=[ MatchAs(name='x')]), MatchAs(name='y')]), body=[ Expr( value=Constant(value=Ellipsis))])])], type_ignores=[])
在版本 3.10 中添加。
类型参数¶
类型参数 可以存在于类、函数和类型别名中。
- class ast.TypeVar(name, bound)¶
一个
typing.TypeVar。name是类型变量的名称。bound是绑定或约束(如果有)。如果bound是一个Tuple,它表示约束;否则它表示绑定。>>> print(ast.dump(ast.parse("type Alias[T: int] = list[T]"), indent=4)) Module( body=[ TypeAlias( name=Name(id='Alias', ctx=Store()), type_params=[ TypeVar( name='T', bound=Name(id='int', ctx=Load()))], value=Subscript( value=Name(id='list', ctx=Load()), slice=Name(id='T', ctx=Load()), ctx=Load()))], type_ignores=[])
在 3.12 版本中添加。
- class ast.ParamSpec(name)¶
一个
typing.ParamSpec。name是参数规范的名称。>>> print(ast.dump(ast.parse("type Alias[**P] = Callable[P, int]"), indent=4)) Module( body=[ TypeAlias( name=Name(id='Alias', ctx=Store()), type_params=[ ParamSpec(name='P')], 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()))], type_ignores=[])
在 3.12 版本中添加。
- class ast.TypeVarTuple(name)¶
一个
typing.TypeVarTuple。name是类型变量元组的名称。>>> 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')], value=Subscript( value=Name(id='tuple', ctx=Load()), slice=Tuple( elts=[ Starred( value=Name(id='Ts', ctx=Load()), ctx=Load())], ctx=Load()), ctx=Load()))], type_ignores=[])
在 3.12 版本中添加。
函数和类定义¶
- class ast.FunctionDef(name, args, body, decorator_list, returns, type_comment, type_params)¶
函数定义。
name是函数名称的原始字符串。args是一个arguments节点。body是函数内部的节点列表。decorator_list是要应用的装饰器列表,按最外层优先存储(即列表中的第一个装饰器最后应用)。returns是返回值注释。type_params是 类型参数 的列表。
- 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( 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)¶
函数的参数。
- class ast.arg(arg, annotation, type_comment)¶
列表中的单个参数。
arg是参数名称的原始字符串;annotation是它的注释,例如Name节点。- type_comment¶
type_comment是一个可选字符串,包含类型注释作为注释
>>> print(ast.dump(ast.parse("""\ ... @decorator1 ... @decorator2 ... def f(a: 'annotation', b=1, c=2, *d, e, f=3, **g) -> 'return annotation': ... pass ... """), indent=4)) Module( body=[ FunctionDef( name='f', args=arguments( posonlyargs=[], args=[ arg( arg='a', annotation=Constant(value='annotation')), arg(arg='b'), arg(arg='c')], vararg=arg(arg='d'), kwonlyargs=[ arg(arg='e'), arg(arg='f')], kw_defaults=[ None, Constant(value=3)], kwarg=arg(arg='g'), defaults=[ Constant(value=1), Constant(value=2)]), body=[ Pass()], decorator_list=[ Name(id='decorator1', ctx=Load()), Name(id='decorator2', ctx=Load())], returns=Constant(value='return annotation'), type_params=[])], type_ignores=[])
- class ast.Return(value)¶
一个
return语句。>>> print(ast.dump(ast.parse('return 4'), indent=4)) Module( body=[ Return( value=Constant(value=4))], type_ignores=[])
- class ast.Yield(value)¶
- class ast.YieldFrom(value)¶
一个
yield或yield from表达式。由于这些是表达式,因此如果发送回的值未使用,则必须将其包装在Expr节点中。>>> print(ast.dump(ast.parse('yield x'), indent=4)) Module( body=[ Expr( value=Yield( value=Name(id='x', ctx=Load())))], type_ignores=[]) >>> print(ast.dump(ast.parse('yield from x'), indent=4)) Module( body=[ Expr( value=YieldFrom( value=Name(id='x', ctx=Load())))], type_ignores=[])
- class ast.Global(names)¶
- class ast.Nonlocal(names)¶
global和nonlocal语句。names是原始字符串的列表。>>> print(ast.dump(ast.parse('global x,y,z'), indent=4)) Module( body=[ Global( names=[ 'x', 'y', 'z'])], type_ignores=[]) >>> print(ast.dump(ast.parse('nonlocal x,y,z'), indent=4)) Module( body=[ Nonlocal( names=[ 'x', 'y', 'z'])], type_ignores=[])
- class ast.ClassDef(name, bases, keywords, body, decorator_list, type_params)¶
类定义。
name是类名称的原始字符串bases是显式指定基类的节点列表。keywords是一个keyword节点的列表,主要用于 'metaclass'。其他关键字将根据 PEP-3115 传递给元类。body是一个节点列表,表示类定义中的代码。decorator_list是一个节点列表,与FunctionDef中的相同。type_params是 类型参数 的列表。
>>> 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_params=[])], type_ignores=[])
在 3.12 版本中更改: 添加了
type_params。
异步和等待¶
- 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(
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=[])
- 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()的标志中。这将报告放置错误的类型注释的语法错误。没有此标志,类型注释将被忽略,并且选定 AST 节点上的type_comment字段将始终为None。此外,# type: ignore注释的位置将作为Module的type_ignores属性返回(否则它始终为空列表)。此外,如果
mode为'func_type',则输入语法将被修改以对应于 PEP 484 的“签名类型注释”,例如(str, int) -> List[str]。将
feature_version设置为元组(major, minor)将导致“尽力而为”地尝试使用该 Python 版本的语法进行解析。例如,将feature_version=(3, 9)设置为将尝试禁止解析match语句。目前major必须等于3。最低支持版本为(3, 4)(这可能会在未来的 Python 版本中增加);最高版本为sys.version_info[0:2]。“尽力而为”尝试意味着不能保证解析(或解析成功)与在与feature_version相对应的 Python 版本上运行时相同。如果 source 包含空字符 (
\0),则会引发ValueError。警告
请注意,将源代码成功解析为 AST 对象并不保证提供的源代码是有效的 Python 代码,可以执行,因为编译步骤可能会引发进一步的
SyntaxError异常。例如,源代码return 42为 return 语句生成一个有效的 AST 节点,但它不能单独编译(它需要在函数节点内)。特别是,
ast.parse()不会执行任何作用域检查,而编译步骤会执行。警告
由于 Python 的 AST 编译器中的堆栈深度限制,可以使用足够大/复杂的字符串使 Python 解释器崩溃。
在 3.8 版中更改: 添加了
type_comments、mode='func_type'和feature_version。
- ast.unparse(ast_obj)¶
反解析
ast.AST对象并生成一个字符串,其中包含代码,如果使用ast.parse()重新解析,该代码将生成等效的ast.AST对象。警告
生成的代码字符串不一定等于生成
ast.AST对象的原始代码(不包括任何编译器优化,例如常量元组/冻结集)。警告
尝试解析高度复杂的表达式会导致
RecursionError。在 3.9 版本中添加。
- ast.literal_eval(node_or_string)¶
评估表达式节点或仅包含 Python 字面量或容器显示的字符串。提供的字符串或节点只能包含以下 Python 字面量结构:字符串、字节、数字、元组、列表、字典、集合、布尔值、
None和Ellipsis。这可用于评估包含 Python 值的字符串,而无需自行解析这些值。它无法评估任意复杂的表达式,例如涉及运算符或索引的表达式。
此函数过去曾被记录为“安全”,但没有定义其含义。这是误导性的。此函数专门设计为不执行 Python 代码,与更通用的
eval()不同。没有命名空间,没有名称查找,也不能调用外部函数。但它并非没有攻击风险:相对较小的输入会导致内存耗尽或 C 栈耗尽,从而使进程崩溃。某些输入也可能导致过度 CPU 消耗,从而造成拒绝服务攻击。因此,不建议在不受信任的数据上调用此函数。警告
由于 Python 的 AST 编译器中的栈深度限制,可能会导致 Python 解释器崩溃。
它可能会根据格式错误的输入引发
ValueError、TypeError、SyntaxError、MemoryError和RecursionError。3.2 版本中的变更: 现在允许字节和集合字面量。
3.9 版本中的变更: 现在支持使用
'set()'创建空集合。3.10 版本中的变更: 对于字符串输入,现在会去除开头的空格和制表符。
- ast.get_docstring(node, clean=True)¶
返回给定 node 的文档字符串(必须是
FunctionDef、AsyncFunctionDef、ClassDef或Module节点),如果它没有文档字符串,则返回None。如果 clean 为 True,则使用inspect.cleandoc()清理文档字符串的缩进。3.5 版本中的变更: 现在支持
AsyncFunctionDef。
- ast.get_source_segment(source, node, *, padded=False)¶
获取生成 node 的 source 的源代码段。如果某些位置信息(
lineno、end_lineno、col_offset或end_col_offset)丢失,则返回None。如果 padded 为
True,则多行语句的第一行将用空格填充以匹配其原始位置。在 3.8 版本中添加。
- ast.fix_missing_locations(node)¶
当使用
compile()编译节点树时,编译器需要每个支持它们的节点的lineno和col_offset属性。对于生成的节点,手动填写这些属性比较繁琐,因此此辅助函数会递归地添加这些属性(如果尚未设置),方法是将它们设置为父节点的值。它从 node 开始递归地工作。
- ast.increment_lineno(node, n=1)¶
将从 node 开始的树中每个节点的行号和结束行号增加 n。这对于将代码“移动”到文件中的不同位置很有用。
- ast.copy_location(new_node, old_node)¶
如果可能,将源位置(
lineno、col_offset、end_lineno和end_col_offset)从 old_node 复制到 new_node,并返回 new_node。
- ast.iter_fields(node)¶
为 node 上存在的
node._fields中的每个字段生成一个(fieldname, value)元组。
- ast.iter_child_nodes(node)¶
生成node的所有直接子节点,即所有节点字段和所有节点列表字段的项目。
- ast.walk(node)¶
递归地生成从node开始的树中的所有后代节点(包括node本身),没有指定顺序。如果您只想就地修改节点并且不关心上下文,这很有用。
- class ast.NodeVisitor¶
一个节点访问器基类,它遍历抽象语法树并为找到的每个节点调用访问器函数。此函数可能会返回值,该返回值由
visit()方法转发。此类旨在被子类化,子类添加访问器方法。
- visit(node)¶
访问节点。默认实现调用名为
self.visit_classname的方法,其中classname是节点类的名称,或者generic_visit()(如果该方法不存在)。
- generic_visit(node)¶
此访问器对节点的所有子节点调用
visit()。请注意,具有自定义访问器方法的节点的子节点不会被访问,除非访问器调用
generic_visit()或自己访问它们。
- visit_Constant(node)¶
处理所有常量节点。
如果您想在遍历期间对节点进行更改,请不要使用
NodeVisitor。为此,存在一个特殊的访问器(NodeTransformer),它允许修改。自版本 3.8 起弃用: 方法
visit_Num()、visit_Str()、visit_Bytes()、visit_NameConstant()和visit_Ellipsis()现在已弃用,并且在未来的 Python 版本中不会被调用。添加visit_Constant()方法来处理所有常量节点。
- class ast.NodeTransformer¶
一个
NodeVisitor子类,它遍历抽象语法树并允许修改节点。NodeTransformer将遍历 AST 并使用访问器方法的返回值来替换或删除旧节点。如果访问器方法的返回值为None,则该节点将从其位置删除,否则它将被返回值替换。返回值可能是原始节点,在这种情况下不会进行替换。以下是一个将所有名称查找(
foo)重写为data['foo']的示例转换器class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load()), slice=Constant(value=node.id), ctx=node.ctx )
请记住,如果您正在操作的节点具有子节点,您必须自己转换子节点或首先对节点调用
generic_visit()方法。对于属于语句集合的节点(适用于所有语句节点),访问器也可以返回节点列表,而不仅仅是单个节点。
如果
NodeTransformer引入了新的节点(不是原始树的一部分)而没有为它们提供位置信息(例如lineno),则应使用新子树调用fix_missing_locations()来重新计算位置信息tree = ast.parse('foo', mode='eval') new_tree = fix_missing_locations(RewriteName().visit(tree))
通常您像这样使用转换器
node = YourTransformer().visit(node)
- ast.dump(node, annotate_fields=True, include_attributes=False, *, indent=None)¶
返回node中树的格式化转储。这主要用于调试目的。如果annotate_fields为真(默认情况下),则返回的字符串将显示字段的名称和值。如果annotate_fields为假,则结果字符串将通过省略明确的字段名称而更加紧凑。默认情况下不会转储诸如行号和列偏移量之类的属性。如果需要,可以将include_attributes设置为真。
如果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¶
显示帮助消息并退出。
- --no-type-comments¶
不解析类型注释。
- -a, --include-attributes¶
包含属性,例如行号和列偏移量。
如果指定了 infile,则解析其内容为 AST 并将其转储到 stdout。否则,内容将从 stdin 读取。
另请参阅
Green Tree Snakes,一个外部文档资源,详细介绍了使用 Python AST 的方法。
ASTTokens 使用生成它们的源代码中的标记位置和文本对 Python AST 进行注释。这对于进行源代码转换的工具很有帮助。
leoAst.py 通过在标记和 ast 节点之间插入双向链接,统一了基于标记和基于解析树的 Python 程序视图。
LibCST 将代码解析为一个具体语法树,它看起来像一个 ast 树,并保留所有格式细节。它对于构建自动重构(codemod)应用程序和 linter 很有用。
Parso 是一个 Python 解析器,它支持错误恢复和针对不同 Python 版本(在多个 Python 版本中)的往返解析。Parso 还可以列出 Python 文件中的多个语法错误。