ast
--- 抽象语法树¶
源代码: Lib/ast.py
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)
| Interpolation(expr value, constant str, int conversion, expr? format_spec)
| JoinedStr(expr* values)
| TemplateStr(expr* values)
| Constant(constant value, string? kind)
-- the following expression can appear in assignment context
| Attribute(expr value, identifier attr, expr_context ctx)
| Subscript(expr value, expr slice, expr_context ctx)
| Starred(expr value, expr_context ctx)
| Name(identifier id, expr_context ctx)
| List(expr* elts, expr_context ctx)
| Tuple(expr* elts, expr_context ctx)
-- can appear only in Subscript
| Slice(expr? lower, expr? upper, expr? step)
-- col_offset is the byte offset in the utf8 string the parser uses
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
expr_context = Load | Store | Del
boolop = And | Or
operator = Add | Sub | Mult | MatMult | Div | Mod | Pow | LShift
| RShift | BitOr | BitXor | BitAnd | FloorDiv
unaryop = Invert | Not | UAdd | USub
cmpop = Eq | NotEq | Lt | LtE | Gt | GtE | Is | IsNot | In | NotIn
comprehension = (expr target, expr iter, expr* ifs, int is_async)
excepthandler = ExceptHandler(expr? type, identifier? name, stmt* body)
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
arguments = (arg* posonlyargs, arg* args, arg? vararg, arg* kwonlyargs,
expr* kw_defaults, arg? kwarg, expr* defaults)
arg = (identifier arg, expr? annotation, string? type_comment)
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
-- keyword arguments supplied to call (NULL identifier for **kwargs)
keyword = (identifier? arg, expr value)
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
-- import name with optional 'as' alias.
alias = (identifier name, identifier? asname)
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
withitem = (expr context_expr, expr? optional_vars)
match_case = (pattern pattern, expr? guard, stmt* body)
pattern = MatchValue(expr value)
| MatchSingleton(constant value)
| MatchSequence(pattern* patterns)
| MatchMapping(expr* keys, pattern* patterns, identifier? rest)
| MatchClass(expr cls, pattern* patterns, identifier* kwd_attrs, pattern* kwd_patterns)
| MatchStar(identifier? name)
-- The optional "rest" MatchMapping parameter handles capturing extra mapping keys
| MatchAs(pattern? pattern, identifier? name)
| MatchOr(pattern* patterns)
attributes (int lineno, int col_offset, int end_lineno, int end_col_offset)
type_ignore = TypeIgnore(int lineno, string tag)
type_param = TypeVar(identifier name, expr? bound, expr? default_value)
| ParamSpec(identifier name, expr? default_value)
| TypeVarTuple(identifier name, expr? default_value)
attributes (int lineno, int col_offset, int end_lineno, int end_col_offset)
}
节点类¶
- class ast.AST¶
这是所有 AST 节点类的基类。实际的节点类派生自
Parser/Python.asdl
文件,该文件在上方有转载。它们定义在_ast
C 模块中,并在ast
中重新导出。抽象语法中每个左侧符号都有一个定义的类(例如,
ast.stmt
或ast.expr
)。此外,右侧的每个构造器也都有一个定义的类;这些类继承自左侧树的类。例如,ast.BinOp
继承自ast.expr
。对于带有备选项(即“和类型”)的产生式规则,左侧的类是抽象的:只有特定构造器节点的实例会被创建。- _fields¶
每个具体类都有一个属性
_fields
,它给出了所有子节点的名称。每个具体类的实例都有一个对应于每个子节点的属性,其类型在语法中定义。例如,
ast.BinOp
实例有一个类型为ast.expr
的属性left
。如果这些属性在语法中被标记为可选的(使用问号),其值可能为
None
。如果属性可以有零个或多个值(用星号标记),这些值会表示为 Python 列表。在使用compile()
编译 AST 时,所有可能的属性都必须存在并且具有有效的值。
- _field_types¶
每个具体类上的
_field_types
属性是一个字典,将字段名(也列在_fields
中)映射到它们的类型。>>> ast.TypeVar._field_types {'name': <class 'str'>, 'bound': ast.expr | None, 'default_value': ast.expr | None}
在 3.13 版本加入。
- lineno¶
- col_offset¶
- end_lineno¶
- end_col_offset¶
ast.expr
和ast.stmt
子类的实例具有lineno
、col_offset
、end_lineno
和end_col_offset
属性。lineno
和end_lineno
是源代码文本范围的第一行和最后一行行号(1-indexed,所以第一行是第1行),而col_offset
和end_col_offset
是生成该节点的第一个和最后一个词法单元对应的 UTF-8 字节偏移量。记录 UTF-8 偏移量是因为解析器内部使用 UTF-8。请注意,结束位置不是编译器所必需的,因此是可选的。结束偏移量在最后一个符号*之后*,例如,可以使用
source_line[node.col_offset : node.end_col_offset]
获取单行表达式节点的源代码片段。
类
ast.T
的构造函数按以下方式解析其参数:如果存在位置参数,其数量必须与
T._fields
中的项数相同;它们将被赋值为这些名称的属性。如果存在关键字参数,它们将把同名属性设置为给定的值。
例如,要创建并填充一个
ast.UnaryOp
节点,你可以使用:node = ast.UnaryOp(ast.USub(), ast.Constant(5, lineno=0, col_offset=0), lineno=0, col_offset=0)
如果构造函数中省略了在语法中为可选的字段,则其默认值为
None
。如果省略了列表字段,则其默认值为空列表。如果省略了类型为ast.expr_context
的字段,则其默认值为Load()
。如果省略任何其他字段,将引发DeprecationWarning
,并且 AST 节点将不包含此字段。在 Python 3.15 中,这种情况将引发错误。
在 3.8 版更改: 类 ast.Constant
现在用于所有常量。
在 3.9 版更改: 简单索引由其值表示,扩展切片由元组表示。
在 3.14 版更改: AST
节点的 __repr__()
输出包括节点字段的值。
自 3.8 版起不推荐使用: 旧的类 ast.Num
、ast.Str
、ast.Bytes
、ast.NameConstant
和 ast.Ellipsis
仍然可用,但它们将在未来的 Python 版本中被移除。在此期间,实例化它们将返回一个不同类的实例。
自 3.9 版起不推荐使用: 旧的类 ast.Index
和 ast.ExtSlice
仍然可用,但它们将在未来的 Python 版本中被移除。在此期间,实例化它们将返回一个不同类的实例。
自 3.13 版起不推荐使用,将在 3.15 版中移除: 旧版本的 Python 允许创建缺少必需字段的 AST 节点。类似地,AST 节点构造函数允许任意关键字参数,这些参数被设置为 AST 节点的属性,即使它们不匹配 AST 节点的任何字段。此行为已弃用,并将在 Python 3.15 中移除。
备注
此处显示的特定节点类的描述最初改编自优秀的 Green Tree Snakes 项目及其所有贡献者。
根节点¶
- class ast.Module(body, type_ignores)¶
一个 Python 模块,如同文件输入一样。在默认的
"exec"
mode 下,由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))])
- 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 对象。所代表的值可以是str
、bytes
、int
、float
、complex
和bool
的实例,以及常量None
和Ellipsis
。>>> 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
中。
- 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())]), conversion=-1, format_spec=JoinedStr( values=[ Constant(value='.3')]))]))
- class ast.TemplateStr(values, /)¶
在 3.14 版本加入。
表示模板字符串字面值的节点,由一系列
Interpolation
和Constant
节点组成。这些节点可以按任何顺序排列,并且不必交错。>>> expr = ast.parse('t"{name} finished {place:ordinal}"', mode='eval') >>> print(ast.dump(expr, indent=4)) Expression( body=TemplateStr( values=[ Interpolation( value=Name(id='name', ctx=Load()), str='name', conversion=-1), Constant(value=' finished '), Interpolation( value=Name(id='place', ctx=Load()), str='place', conversion=-1, format_spec=JoinedStr( values=[ Constant(value='ordinal')]))]))
- class ast.Interpolation(value, str, conversion, format_spec=None)¶
在 3.14 版本加入。
表示模板字符串字面值中单个插值字段的节点。
value
是任何表达式节点(例如字面值、变量或函数调用)。其含义与FormattedValue.value
相同。str
是一个包含插值表达式文本的常量。conversion
是一个整数其含义与
FormattedValue.conversion
相同。format_spec
是一个JoinedStr
节点,表示值的格式,如果未指定格式,则为None
。conversion
和format_spec
可以同时设置。其含义与FormattedValue.format_spec
相同。
- class ast.List(elts, ctx)¶
- class ast.Tuple(elts, ctx)¶
列表或元组。
elts
包含一个表示元素的节点列表。ctx
在容器是赋值目标(即(x,y)=something
)时为Store
,否则为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()))]) >>> print(ast.dump(ast.parse('a = 1'), indent=4)) Module( body=[ Assign( targets=[ Name(id='a', ctx=Store())], value=Constant(value=1))]) >>> print(ast.dump(ast.parse('del a'), indent=4)) Module( body=[ Delete( targets=[ Name(id='a', ctx=Del())])])
- class ast.Starred(value, ctx)¶
一个
*var
变量引用。value
保存变量,通常是一个Name
节点。当构建带*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()))])
表达式¶
- class ast.Expr(value)¶
当一个表达式(例如函数调用)作为独立的语句出现,而其返回值未被使用或存储时,它会被包装在此容器中。
value
保存本节中的其他节点之一,即Constant
、Name
、Lambda
、Yield
或YieldFrom
节点。>>> print(ast.dump(ast.parse('-a'), indent=4)) Module( body=[ Expr( value=UnaryOp( op=USub(), operand=Name(id='a', ctx=Load())))])
- class ast.UnaryOp(op, operand)¶
一元操作。
op
是运算符,operand
是任何表达式节点。
- class ast.UAdd¶
- class ast.USub¶
- class ast.Not¶
- class ast.Invert¶
一元运算符标记。
Not
是not
关键字,Invert
是~
运算符。>>> print(ast.dump(ast.parse('not x', mode='eval'), indent=4)) Expression( body=UnaryOp( op=Not(), operand=Name(id='x', ctx=Load())))
- class ast.BinOp(left, op, right)¶
二元操作(如加法或除法)。
op
是运算符,left
和right
是任意表达式节点。>>> print(ast.dump(ast.parse('x + y', mode='eval'), indent=4)) Expression( body=BinOp( left=Name(id='x', ctx=Load()), op=Add(), right=Name(id='y', ctx=Load())))
- class ast.Add¶
- class ast.Sub¶
- class ast.Mult¶
- class ast.Div¶
- class ast.FloorDiv¶
- class ast.Mod¶
- class ast.Pow¶
- class ast.LShift¶
- class ast.RShift¶
- class ast.BitOr¶
- class ast.BitXor¶
- class ast.BitAnd¶
- class ast.MatMult¶
二元运算符标记。
- class ast.BoolOp(op, values)¶
布尔运算,“or” 或 “and”。
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
对象列表,表示按关键字传递的参数。
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()), is_async=0)])) >>> print(ast.dump( ... ast.parse('{x: x**2 for x in numbers}', mode='eval'), ... indent=4, ... )) Expression( body=DictComp( key=Name(id='x', ctx=Load()), value=BinOp( left=Name(id='x', ctx=Load()), op=Pow(), right=Constant(value=2)), generators=[ comprehension( target=Name(id='x', ctx=Store()), iter=Name(id='numbers', ctx=Load()), is_async=0)])) >>> print(ast.dump( ... ast.parse('{x for x in numbers}', mode='eval'), ... indent=4, ... )) Expression( body=SetComp( elt=Name(id='x', ctx=Load()), generators=[ comprehension( target=Name(id='x', ctx=Store()), iter=Name(id='numbers', ctx=Load()), is_async=0)]))
- class ast.comprehension(target, iter, ifs, is_async)¶
推导式中的一个
for
子句。target
是用于每个元素的引用 - 通常是Name
或Tuple
节点。iter
是要迭代的对象。ifs
是一个测试表达式列表:每个for
子句可以有多个ifs
。is_async
表示一个推导式是异步的(使用async for
而不是for
)。该值为整数(0 或 1)。>>> print(ast.dump(ast.parse('[ord(c) for line in file for c in line]', mode='eval'), ... indent=4)) # Multiple comprehensions in one. Expression( body=ListComp( elt=Call( func=Name(id='ord', ctx=Load()), args=[ Name(id='c', ctx=Load())]), generators=[ comprehension( target=Name(id='line', ctx=Store()), iter=Name(id='file', ctx=Load()), is_async=0), comprehension( target=Name(id='c', ctx=Store()), iter=Name(id='line', ctx=Load()), is_async=0)])) >>> print(ast.dump(ast.parse('(n**2 for n in it if n>5 if n<10)', mode='eval'), ... indent=4)) # generator comprehension Expression( body=GeneratorExp( elt=BinOp( left=Name(id='n', ctx=Load()), op=Pow(), right=Constant(value=2)), generators=[ comprehension( target=Name(id='n', ctx=Store()), iter=Name(id='it', ctx=Load()), ifs=[ Compare( left=Name(id='n', ctx=Load()), ops=[ Gt()], comparators=[ Constant(value=5)]), Compare( left=Name(id='n', ctx=Load()), ops=[ Lt()], comparators=[ Constant(value=10)])], is_async=0)])) >>> print(ast.dump(ast.parse('[i async for i in soc]', mode='eval'), ... indent=4)) # Async comprehension Expression( body=ListComp( elt=Name(id='i', ctx=Load()), generators=[ comprehension( target=Name(id='i', ctx=Store()), iter=Name(id='soc', ctx=Load()), is_async=1)]))
语句¶
- class ast.Assign(targets, value, type_comment)¶
一个赋值语句。
targets
是一个节点列表,value
是一个单独的节点。targets
中的多个节点表示将相同的值赋给每个节点。解包通过在targets
中放入Tuple
或List
来表示。- type_comment¶
type_comment
是一个可选字符串,带有作为注释的类型注解。
>>> print(ast.dump(ast.parse('a = b = 1'), indent=4)) # Multiple assignment Module( body=[ Assign( targets=[ Name(id='a', ctx=Store()), Name(id='b', ctx=Store())], value=Constant(value=1))]) >>> print(ast.dump(ast.parse('a,b = c'), indent=4)) # Unpacking Module( body=[ Assign( targets=[ Tuple( elts=[ Name(id='a', ctx=Store()), Name(id='b', ctx=Store())], ctx=Store())], value=Name(id='c', ctx=Load()))])
- class ast.AnnAssign(target, annotation, value, simple)¶
带类型注解的赋值。
target
是一个单独的节点,可以是Name
、Attribute
或Subscript
。annotation
是注解,例如Constant
或Name
节点。value
是一个单独的可选节点。simple
总是为 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)]) >>> print(ast.dump(ast.parse('(a): int = 1'), indent=4)) # Annotation with parenthesis Module( body=[ AnnAssign( target=Name(id='a', ctx=Store()), annotation=Name(id='int', ctx=Load()), value=Constant(value=1), simple=0)]) >>> print(ast.dump(ast.parse('a.b: int'), indent=4)) # Attribute annotation Module( body=[ AnnAssign( target=Attribute( value=Name(id='a', ctx=Load()), attr='b', ctx=Store()), annotation=Name(id='int', ctx=Load()), simple=0)]) >>> print(ast.dump(ast.parse('a[1]: int'), indent=4)) # Subscript annotation Module( body=[ AnnAssign( target=Subscript( value=Name(id='a', ctx=Load()), slice=Constant(value=1), ctx=Store()), annotation=Name(id='int', ctx=Load()), simple=0)])
- class ast.AugAssign(target, op, value)¶
增量赋值,例如
a += 1
。在下面的例子中,target
是一个代表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))])
- 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()))])
- class ast.Assert(test, msg)¶
一个断言。
test
包含条件,例如Compare
节点。msg
包含失败消息。>>> print(ast.dump(ast.parse('assert x,y'), indent=4)) Module( body=[ Assert( test=Name(id='x', ctx=Load()), msg=Name(id='y', ctx=Load()))])
- class ast.Delete(targets)¶
表示一个
del
语句。targets
是一个节点列表,例如Name
、Attribute
或Subscript
节点。>>> print(ast.dump(ast.parse('del x,y,z'), indent=4)) Module( body=[ Delete( targets=[ Name(id='x', ctx=Del()), Name(id='y', ctx=Del()), Name(id='z', ctx=Del())])])
- class ast.Pass¶
一个
pass
语句。>>> print(ast.dump(ast.parse('pass'), indent=4)) Module( body=[ Pass()])
- class ast.TypeAlias(name, type_params, value)¶
通过
type
语句创建的类型别名。name
是别名的名称,type_params
是类型形参列表,value
是类型别名的值。>>> print(ast.dump(ast.parse('type Alias = int'), indent=4)) Module( body=[ TypeAlias( name=Name(id='Alias', ctx=Store()), value=Name(id='int', ctx=Load()))])
3.12 新版功能.
其他仅适用于函数或循环内部的语句在其他部分中描述。
导入¶
- class ast.Import(names)¶
一个导入语句。
names
是一个alias
节点列表。>>> print(ast.dump(ast.parse('import x,y,z'), indent=4)) Module( body=[ Import( names=[ alias(name='x'), alias(name='y'), alias(name='z')])])
- class ast.ImportFrom(module, names, level)¶
代表
from x import y
。module
是 'from' 名称的原始字符串,不带任何前导点号,对于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)])
- class ast.alias(name, asname)¶
两个参数都是名称的原始字符串。如果使用常规名称,
asname
可以为None
。>>> print(ast.dump(ast.parse('from ..foo.bar import a as b, c'), indent=4)) Module( body=[ ImportFrom( module='foo.bar', names=[ alias(name='a', asname='b'), alias(name='c')], level=2)])
控制流¶
备注
像 else
这样的可选子句如果不存在,则存储为空列表。
- class ast.If(test, body, orelse)¶
一个
if
语句。test
包含一个节点,例如Compare
节点。body
和orelse
各自包含一个节点列表。elif
子句在 AST 中没有特殊的表示形式,而是作为前一个If
节点的orelse
部分中的额外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))])])])
- 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))])])
- class ast.While(test, body, orelse)¶
一个
while
循环。test
包含条件,例如一个Compare
节点。>>> print(ast.dump(ast.parse(""" ... while x: ... ... ... else: ... ... ... """), indent=4)) Module( body=[ While( test=Name(id='x', ctx=Load()), body=[ Expr( value=Constant(value=Ellipsis))], orelse=[ Expr( value=Constant(value=Ellipsis))])])
- class ast.Break¶
- class ast.Continue¶
break
和continue
语句。>>> print(ast.dump(ast.parse("""\ ... for a in b: ... if a > 5: ... break ... else: ... continue ... ... """), indent=4)) Module( body=[ For( target=Name(id='a', ctx=Store()), iter=Name(id='b', ctx=Load()), body=[ If( test=Compare( left=Name(id='a', ctx=Load()), ops=[ Gt()], comparators=[ Constant(value=5)]), body=[ Break()], orelse=[ Continue()])])])
- class ast.Try(body, handlers, orelse, finalbody)¶
try
块。所有属性都是要执行的节点列表,除了handlers
,它是一个ExceptHandler
节点列表。>>> print(ast.dump(ast.parse(""" ... try: ... ... ... except Exception: ... ... ... except OtherException as e: ... ... ... else: ... ... ... finally: ... ... ... """), indent=4)) Module( body=[ Try( body=[ Expr( value=Constant(value=Ellipsis))], handlers=[ ExceptHandler( type=Name(id='Exception', ctx=Load()), body=[ Expr( value=Constant(value=Ellipsis))]), ExceptHandler( type=Name(id='OtherException', ctx=Load()), name='e', body=[ Expr( value=Constant(value=Ellipsis))])], orelse=[ Expr( value=Constant(value=Ellipsis))], finalbody=[ Expr( value=Constant(value=Ellipsis))])])
- class ast.TryStar(body, handlers, orelse, finalbody)¶
后跟
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))])])])
在 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()])])])
- 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
是as foo
部分的Name
、Tuple
或List
节点,如果未使用该部分则为None
。>>> print(ast.dump(ast.parse("""\ ... with a as b, c as d: ... something(b, d) ... """), indent=4)) Module( body=[ With( items=[ withitem( context_expr=Name(id='a', ctx=Load()), optional_vars=Name(id='b', ctx=Store())), withitem( context_expr=Name(id='c', ctx=Load()), optional_vars=Name(id='d', ctx=Store()))], body=[ Expr( value=Call( func=Name(id='something', ctx=Load()), args=[ Name(id='b', ctx=Load()), Name(id='d', ctx=Load())]))])])
模式匹配¶
- class ast.Match(subject, cases)¶
一个
match
语句。subject
包含匹配的主体(即与各种 case 进行匹配的对象),而cases
包含一个由match_case
节点组成的可迭代对象,代表不同的 case。在 3.10 版本加入。
- class ast.match_case(pattern, guard, body)¶
match
语句中的单个 case 模式。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())), body=[ Expr( value=Constant(value=Ellipsis))])])])
在 3.10 版本加入。
- class ast.MatchValue(value)¶
一个通过相等性比较的匹配字面值或值模式。
value
是一个表达式节点。允许的值节点受到 match 语句文档中所述的限制。如果匹配主体等于求值后的值,则此模式匹配成功。>>> print(ast.dump(ast.parse(""" ... match x: ... case "Relevant": ... ... ... """), indent=4)) Module( body=[ Match( subject=Name(id='x', ctx=Load()), cases=[ match_case( pattern=MatchValue( value=Constant(value='Relevant')), body=[ Expr( value=Constant(value=Ellipsis))])])])
在 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))])])])
在 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))])])])
在 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))])])])
在 3.10 版本加入。
- class ast.MatchMapping(keys, patterns, rest)¶
一个匹配映射模式。
keys
是一个表达式节点序列。patterns
是一个对应的模式节点序列。rest
是一个可选名称,可用于捕获剩余的映射元素。允许的键表达式受到 match 语句文档中所述的限制。如果主体是映射,所有求值后的键表达式都存在于映射中,并且每个键对应的值都与相应的子模式匹配,则此模式匹配成功。如果
rest
不为None
,且整个映射模式匹配成功,则包含剩余映射元素的字典将绑定到该名称。>>> print(ast.dump(ast.parse(""" ... match x: ... case {1: _, 2: _}: ... ... ... case {**rest}: ... ... ... """), indent=4)) Module( body=[ Match( subject=Name(id='x', ctx=Load()), cases=[ match_case( pattern=MatchMapping( keys=[ Constant(value=1), Constant(value=2)], patterns=[ MatchAs(), MatchAs()]), body=[ Expr( value=Constant(value=Ellipsis))]), match_case( pattern=MatchMapping(rest='rest'), body=[ Expr( value=Constant(value=Ellipsis))])])])
在 3.10 版本加入。
- class ast.MatchClass(cls, patterns, kwd_attrs, kwd_patterns)¶
一个匹配类模式。
cls
是一个给出要匹配的名义类的表达式。patterns
是一个模式节点序列,将与类定义的模式匹配属性序列进行匹配。kwd_attrs
是要匹配的附加属性序列(在类模式中作为关键字参数指定),kwd_patterns
是相应的模式(在类模式中作为关键字值指定)。如果主体是被提名类的实例,所有位置模式都与相应的类定义属性匹配,并且任何指定的关键字属性都与它们相应的模式匹配,则此模式匹配成功。
注意:类可以定义一个返回 self 的属性,以便将模式节点与被匹配的实例进行匹配。如 match 语句文档所述,一些内置类型也以这种方式进行匹配。
>>> print(ast.dump(ast.parse(""" ... match x: ... case Point2D(0, 0): ... ... ... case Point3D(x=0, y=0, z=0): ... ... ... """), indent=4)) Module( body=[ Match( subject=Name(id='x', ctx=Load()), cases=[ match_case( pattern=MatchClass( cls=Name(id='Point2D', ctx=Load()), patterns=[ MatchValue( value=Constant(value=0)), MatchValue( value=Constant(value=0))]), body=[ Expr( value=Constant(value=Ellipsis))]), match_case( pattern=MatchClass( cls=Name(id='Point3D', ctx=Load()), kwd_attrs=[ 'x', 'y', 'z'], kwd_patterns=[ MatchValue( value=Constant(value=0)), MatchValue( value=Constant(value=0)), MatchValue( value=Constant(value=0))]), body=[ Expr( value=Constant(value=Ellipsis))])])])
在 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))])])])
在 3.10 版本加入。
- class ast.MatchOr(patterns)¶
一个匹配“or-pattern”。一个 or-pattern 会将其每个子模式依次与主体进行匹配,直到有一个匹配成功。此时,or-pattern 被视为成功。如果所有子模式都匹配失败,则 or-pattern 失败。
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))])])])
在 3.10 版本加入。
类型注解¶
- class ast.TypeIgnore(lineno, tag)¶
位于 lineno 行的
# type: ignore
注释。 tag 是由# type: ignore <tag>
形式指定的可选标签。>>> print(ast.dump(ast.parse('x = 1 # type: ignore', type_comments=True), indent=4)) Module( body=[ Assign( targets=[ Name(id='x', ctx=Store())], value=Constant(value=1))], type_ignores=[ TypeIgnore(lineno=1, tag='')]) >>> print(ast.dump(ast.parse('x: bool = 1 # type: ignore[assignment]', type_comments=True), indent=4)) Module( body=[ AnnAssign( target=Name(id='x', ctx=Store()), annotation=Name(id='bool', ctx=Load()), value=Constant(value=1), simple=1)], type_ignores=[ TypeIgnore(lineno=1, tag='[assignment]')])
备注
当 type_comments 参数设置为
False
(默认值)时,不会生成TypeIgnore
节点。更多详情请参阅ast.parse()
。在 3.8 版本加入。
类型形参¶
类型形参可以存在于类、函数和类型别名中。
- class ast.TypeVar(name, bound, default_value)¶
一个
typing.TypeVar
。name
是类型变量的名称。bound
是边界或约束(如果有的话)。如果bound
是一个Tuple
,它代表约束;否则它代表边界。default_value
是默认值;如果TypeVar
没有默认值,此属性将被设置为None
。>>> print(ast.dump(ast.parse("type Alias[T: int = bool] = list[T]"), indent=4)) Module( body=[ TypeAlias( name=Name(id='Alias', ctx=Store()), type_params=[ TypeVar( name='T', bound=Name(id='int', ctx=Load()), default_value=Name(id='bool', ctx=Load()))], value=Subscript( value=Name(id='list', ctx=Load()), slice=Name(id='T', ctx=Load()), ctx=Load()))])
3.12 新版功能.
在 3.13 版本发生变更: 添加了 default_value 形参。
- class ast.ParamSpec(name, default_value)¶
一个
typing.ParamSpec
。name
是参数规范的名称。default_value
是默认值;如果ParamSpec
没有默认值,此属性将被设置为None
。>>> print(ast.dump(ast.parse("type Alias[**P = [int, str]] = Callable[P, int]"), indent=4)) Module( body=[ TypeAlias( name=Name(id='Alias', ctx=Store()), type_params=[ ParamSpec( name='P', default_value=List( elts=[ Name(id='int', ctx=Load()), Name(id='str', ctx=Load())], ctx=Load()))], value=Subscript( value=Name(id='Callable', ctx=Load()), slice=Tuple( elts=[ Name(id='P', ctx=Load()), Name(id='int', ctx=Load())], ctx=Load()), ctx=Load()))])
3.12 新版功能.
在 3.13 版本发生变更: 添加了 default_value 形参。
- class ast.TypeVarTuple(name, default_value)¶
一个
typing.TypeVarTuple
。name
是类型变量元组的名称。default_value
是默认值;如果TypeVarTuple
没有默认值,此属性将被设置为None
。>>> print(ast.dump(ast.parse("type Alias[*Ts = ()] = tuple[*Ts]"), indent=4)) Module( body=[ TypeAlias( name=Name(id='Alias', ctx=Store()), type_params=[ TypeVarTuple( name='Ts', default_value=Tuple(ctx=Load()))], value=Subscript( value=Name(id='tuple', ctx=Load()), slice=Tuple( elts=[ Starred( value=Name(id='Ts', ctx=Load()), ctx=Load())], ctx=Load()), ctx=Load()))])
3.12 新版功能.
在 3.13 版本发生变更: 添加了 default_value 形参。
函数和类定义¶
- class ast.FunctionDef(name, args, body, decorator_list, returns, type_comment, type_params)¶
一个函数定义。
name
是函数名的原始字符串。args
是一个arguments
节点。body
是函数内部的节点列表。decorator_list
是要应用的装饰器列表,按从外到内的顺序存储(即列表中的第一个装饰器将最后应用)。returns
是返回值的注解。type_params
是一个 类型形参 的列表。
- type_comment¶
type_comment
是一个可选字符串,带有作为注释的类型注解。
在 3.12 版本发生变更: 添加了
type_params
。
- class ast.Lambda(args, body)¶
lambda
是一个可以在表达式内部使用的最小函数定义。与FunctionDef
不同,body
包含一个单个节点。>>> print(ast.dump(ast.parse('lambda x,y: ...'), indent=4)) Module( body=[ Expr( value=Lambda( args=arguments( args=[ arg(arg='x'), arg(arg='y')]), body=Constant(value=Ellipsis)))])
- class ast.arguments(posonlyargs, args, vararg, kwonlyargs, kw_defaults, kwarg, defaults)¶
函数的参数。
- class ast.arg(arg, annotation, type_comment)¶
列表中的单个参数。
arg
是参数名的原始字符串;annotation
是它的注解,例如一个Name
节点。- type_comment¶
type_comment
是一个可选字符串,包含作为注释的类型注解。
>>> print(ast.dump(ast.parse("""\ ... @decorator1 ... @decorator2 ... def f(a: 'annotation', b=1, c=2, *d, e, f=3, **g) -> 'return annotation': ... pass ... """), indent=4)) Module( body=[ FunctionDef( name='f', args=arguments( args=[ arg( arg='a', annotation=Constant(value='annotation')), arg(arg='b'), arg(arg='c')], vararg=arg(arg='d'), kwonlyargs=[ arg(arg='e'), arg(arg='f')], kw_defaults=[ None, Constant(value=3)], kwarg=arg(arg='g'), defaults=[ Constant(value=1), Constant(value=2)]), body=[ Pass()], decorator_list=[ Name(id='decorator1', ctx=Load()), Name(id='decorator2', ctx=Load())], returns=Constant(value='return annotation'))])
- class ast.Return(value)¶
一个
return
语句。>>> print(ast.dump(ast.parse('return 4'), indent=4)) Module( body=[ Return( value=Constant(value=4))])
- class ast.Yield(value)¶
- class ast.YieldFrom(value)¶
一个
yield
或yield from
表达式。因为这些是表达式,如果返回的值不被使用,它们必须被包装在一个Expr
节点中。>>> print(ast.dump(ast.parse('yield x'), indent=4)) Module( body=[ Expr( value=Yield( value=Name(id='x', ctx=Load())))]) >>> print(ast.dump(ast.parse('yield from x'), indent=4)) Module( body=[ Expr( value=YieldFrom( value=Name(id='x', ctx=Load())))])
- class ast.Global(names)¶
- class ast.Nonlocal(names)¶
global
和nonlocal
语句。names
是原始字符串的列表。>>> print(ast.dump(ast.parse('global x,y,z'), indent=4)) Module( body=[ Global( names=[ 'x', 'y', 'z'])]) >>> print(ast.dump(ast.parse('nonlocal x,y,z'), indent=4)) Module( body=[ Nonlocal( names=[ 'x', 'y', 'z'])])
- class ast.ClassDef(name, bases, keywords, body, decorator_list, type_params)¶
一个类定义。
name
是类名的原始字符串。bases
是显式指定的基类的节点列表。keywords
是keyword
节点的列表,主要用于‘metaclass’。其他关键字将根据 PEP 3115 传递给元类。body
是表示类定义内部代码的节点列表。decorator_list
是节点列表,与FunctionDef
中一样。type_params
是一个 类型形参 的列表。
>>> print(ast.dump(ast.parse("""\ ... @decorator1 ... @decorator2 ... class Foo(base1, base2, metaclass=meta): ... pass ... """), indent=4)) Module( body=[ ClassDef( name='Foo', bases=[ Name(id='base1', ctx=Load()), Name(id='base2', ctx=Load())], keywords=[ keyword( arg='metaclass', value=Name(id='meta', ctx=Load()))], body=[ Pass()], decorator_list=[ Name(id='decorator1', ctx=Load()), Name(id='decorator2', ctx=Load())])])
在 3.12 版本发生变更: 添加了
type_params
。
Async 和 await¶
- class ast.AsyncFunctionDef(name, args, body, decorator_list, returns, type_comment, type_params)¶
一个
async def
函数定义。其字段与FunctionDef
相同。在 3.12 版本发生变更: 添加了
type_params
。
- class ast.Await(value)¶
一个
await
表达式。value
是它等待的对象。仅在AsyncFunctionDef
的主体中有效。
>>> print(ast.dump(ast.parse("""\
... async def f():
... await other_func()
... """), indent=4))
Module(
body=[
AsyncFunctionDef(
name='f',
args=arguments(),
body=[
Expr(
value=Await(
value=Call(
func=Name(id='other_func', ctx=Load()))))])])
- class ast.AsyncFor(target, iter, body, orelse, type_comment)¶
- class ast.AsyncWith(items, body, type_comment)¶
async for
循环和async with
上下文管理器。它们的字段分别与For
和With
相同。仅在AsyncFunctionDef
的主体中有效。
备注
当字符串由 ast.parse()
解析时,返回树上的操作符节点(ast.operator
, ast.unaryop
, ast.cmpop
, ast.boolop
和 ast.expr_context
的子类)将是单例。对一个的更改将反映在所有其他相同值的出现中(例如,ast.Add
)。
ast
辅助函数¶
除了节点类,ast
模块定义了以下用于遍历抽象语法树的实用函数和类:
- ast.parse(source, filename='<unknown>', mode='exec', *, type_comments=False, feature_version=None, optimize=-1)¶
将源代码解析为 AST 节点。等同于
compile(source, filename, mode, flags=FLAGS_VALUE, optimize=optimize)
,其中如果optimize <= 0
,FLAGS_VALUE
是ast.PyCF_ONLY_AST
,否则是ast.PyCF_OPTIMIZED_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, 7)
(并且在未来的 Python 版本中可能会增加);最高版本是sys.version_info[0:2]
。“尽力而为”意味着不保证解析(或解析的成功)与在对应于feature_version
的 Python 版本上运行时相同。如果 source 包含空字符 (
\0
),则会引发ValueError
。警告
请注意,成功将源代码解析为 AST 对象并不能保证所提供的源代码是有效的、可以执行的 Python 代码,因为编译步骤可能会引发进一步的
SyntaxError
异常。例如,源代码return 42
会生成一个有效的返回语句 AST 节点,但它不能单独编译(它需要在一个函数节点内)。特别地,
ast.parse()
不会进行任何作用域检查,而编译步骤会进行这些检查。警告
由于 Python 的 AST 编译器存在栈深度限制,使用足够大或复杂的字符串可能会导致 Python 解释器崩溃。
在 3.8 版本发生变更: 添加了
type_comments
、mode='func_type'
和feature_version
。在 3.13 版本发生变更:
feature_version
的最低支持版本现在是(3, 7)
。添加了optimize
参数。
- ast.unparse(ast_obj)¶
反解析一个
ast.AST
对象,并生成一个代码字符串,如果用ast.parse()
再次解析该字符串,将产生一个等效的ast.AST
对象。警告
生成的代码字符串不一定等于生成
ast.AST
对象的原始代码(在没有任何编译器优化的情况下,例如常量元组/frozensets)。警告
尝试反解析一个高度复杂的表达式将导致
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, show_empty=False)¶
返回 node 中树的格式化转储。这主要用于调试目的。如果 annotate_fields 为 true(默认),返回的字符串将显示字段的名称和值。如果 annotate_fields 为 false,结果字符串将通过省略明确的字段名而更加紧凑。默认情况下不转储行号和列偏移等属性。如果需要,可以将 include_attributes 设置为 true。
如果 indent 是一个非负整数或字符串,那么树将被美化打印,并带有该缩进级别。缩进级别为 0、负数或
""
将只插入换行符。None
(默认值)选择单行表示。使用正整数缩进时,每级缩进该数量的空格。如果 indent 是一个字符串(例如"\t"
),则该字符串将用于每级的缩进。如果 show_empty 为 false(默认值),可选的空列表将从输出中省略。可选的
None
值总是被省略。在 3.9 版更改: 增加了 indent 选项。
在 3.13 版更改: 增加了 show_empty 选项。
>>> print(ast.dump(ast.parse("""\ ... async def f(): ... await other_func() ... """), indent=4, show_empty=True)) Module( body=[ AsyncFunctionDef( name='f', args=arguments( posonlyargs=[], args=[], kwonlyargs=[], kw_defaults=[], defaults=[]), body=[ Expr( value=Await( value=Call( func=Name(id='other_func', ctx=Load()), args=[], keywords=[])))], decorator_list=[], type_params=[])], type_ignores=[])
编译器旗标¶
以下旗标可以传递给 compile()
以改变程序编译的效果
- ast.PyCF_ALLOW_TOP_LEVEL_AWAIT¶
启用对顶层
await
、async for
、async with
和异步推导式的支持。在 3.8 版本加入。
- ast.PyCF_ONLY_AST¶
生成并返回一个抽象语法树,而不是返回一个编译后的代码对象。
- ast.PyCF_OPTIMIZED_AST¶
返回的 AST 将根据
compile()
或ast.parse()
中的 optimize 参数进行优化。在 3.13 版本加入。
- ast.PyCF_TYPE_COMMENTS¶
启用对 PEP 484 和 PEP 526 风格类型注释(
# type: <type>
,# type: ignore <stuff>
)的支持。在 3.8 版本加入。
- ast.compare(a, b, /, *, compare_attributes=False)¶
递归地比较两个 AST。
compare_attributes 影响 AST 属性是否在比较中被考虑。如果 compare_attributes 为
False
(默认值),则属性被忽略。否则它们必须全部相等。这个选项对于检查 AST 是否在结构上相等,但在空格或类似细节上有所不同很有用。属性包括行号和列偏移。在 3.14 版本加入。
命令行用法¶
在 3.9 版本中新增。
ast
模块可以作为脚本从命令行执行。用法很简单
python -m ast [-m <mode>] [-a] [infile]
接受以下选项
- -h, --help¶
显示帮助信息并退出。
- --no-type-comments¶
不解析类型注释。
- -a, --include-attributes¶
包括行号和列偏移等属性。
- --feature-version <version>¶
Python 版本,格式为 3.x(例如,3.10)。默认为解释器的当前版本。
在 3.14 版本加入。
- --show-empty¶
显示空列表和值为
None
的字段。默认为不显示空对象。在 3.14 版本加入。
如果指定了 infile
,其内容将被解析为 AST 并转储到标准输出。否则,内容从标准输入读取。
参见
Green Tree Snakes,一个外部文档资源,提供了有关使用 Python AST 的详细信息。
ASTTokens 会为 Python AST 添加注释,标明生成它们的标记和文本在源代码中的位置。这对于进行源代码转换的工具很有帮助。
leoAst.py 通过在标记和 ast 节点之间插入双向链接,统一了基于标记和基于解析树的 python 程序视图。
LibCST 将代码解析为具体语法树(Concrete Syntax Tree),它看起来像一个 ast 树并保留了所有格式化细节。这对于构建自动重构(codemod)应用程序和 linter 非常有用。
Parso 是一个 Python 解析器,支持对不同 Python 版本(在多个 Python 版本中)的错误恢复和往返解析。Parso 还能够列出你的 Python 文件中的多个语法错误。