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
文件派生的,该文件在 上面 进行了复制。它们在_ast
C 模块中定义,并在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:
!r
repr 格式化97:
!a
ascii 格式化
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 文件中的多个语法错误。