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)
| AsyncFunctionDef(identifier name, arguments args,
stmt* body, expr* decorator_list, expr? returns,
string? type_comment)
| ClassDef(identifier name,
expr* bases,
keyword* keywords,
stmt* body,
expr* decorator_list)
| Return(expr? value)
| Delete(expr* targets)
| Assign(expr* targets, expr value, string? type_comment)
| AugAssign(expr target, operator op, expr value)
-- 'simple' indicates that we annotate simple name without parens
| AnnAssign(expr target, expr annotation, expr? value, int simple)
-- use 'orelse' because else is a keyword in target languages
| For(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment)
| AsyncFor(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment)
| While(expr test, stmt* body, stmt* orelse)
| If(expr test, stmt* body, stmt* orelse)
| With(withitem* items, stmt* body, string? type_comment)
| AsyncWith(withitem* items, stmt* body, string? type_comment)
| Match(expr subject, match_case* cases)
| Raise(expr? exc, expr? cause)
| Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)
| 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)
}
节点类¶
- class ast.AST¶
This is the base of all AST node classes. The actual node classes are derived from the
Parser/Python.asdlfile, which is reproduced above. They are defined in the_astC module and re-exported inast.抽象语法定义的每个左侧符号(比方说,
ast.stmt或者ast.expr)定义了一个类。另外,在抽象语法定义的右侧,对每一个构造器也定义了一个类;这些类继承自树左侧的类。比如,ast.BinOp继承自ast.expr。对于多分支产生式(也就是”和规则”),树右侧的类是抽象的;只有特定构造器结点的实例能被构造。- _fields¶
每个具体类都有个属性
_fields, 用来给出所有子节点的名字。每个具体类的实例对它每个子节点都有一个属性,对应类型如文法中所定义。比如,
ast.BinOp的实例有个属性left,类型是ast.expr.如果这些属性在文法中标记为可选(使用问号),对应值可能会是
None。如果这些属性有零或多个(用星号标记),对应值会用 Python 的列表来表示。所有可能的属性必须在用compile()编译得到 AST 时给出,且是有效的值。
- lineno¶
- col_offset¶
- end_lineno¶
- end_col_offset¶
ast.expr和ast.stmt子类的实例有lineno、col_offset、end_lineno和end_col_offset属性。lineno和end_lineno是源文本跨度的第一行和最后一行的编号(1-索引,所以第一行是 行1),而col_offset和end_col_offset是生成该节点的第一个和最后一个形符的相应 UTF-8 字节偏差。UTF-8 的偏移量被记录下来,因为分析器内部使用 UTF-8。请注意,编译器不要求结束位置,因此是可选的。末端偏移量是在最后一个符号之后,例如可以用
source_line[node.col_offset : node.end_col_offset]得到单行表达式节点的源片段。
类的构造器
ast.T像下面这样解析它的参数:如果有位置参数,它们必须和
T._fields中的元素一样多;他们会像这些名字的属性一样被赋值。如果有关键字参数,它们必须被设为和给定值同名的属性。
比方说,要创建和填充节点
ast.UnaryOp,你得用node = ast.UnaryOp() node.op = ast.USub() node.operand = ast.Constant() node.operand.value = 5 node.operand.lineno = 0 node.operand.col_offset = 0 node.lineno = 0 node.col_offset = 0
或者更紧凑点
node = ast.UnaryOp(ast.USub(), ast.Constant(5, lineno=0, col_offset=0), lineno=0, col_offset=0)
在 3.8 版更改: 类 ast.Constant 现用于所有常量。
在 3.9 版更改: 简单的索引用其值表示,扩展的切片用元组表示。
3.8 版后已移除: 旧的类 ast.Num、ast.Str、ast.Bytes、ast.NameConstant 和 ast.Ellipsis 仍然可用,但它们将在未来的 Python 版本中被删除。在此期间,实例化它们将返回一个不同类的实例。
3.9 版后已移除: 旧的类 ast.Index 和 ast.ExtSlice 仍然可用,但它们将在未来的 Python 版本中被移除。在此期间,实例化它们将返回一个不同类的实例。
备注
这里显示的具体节点类的描述最初是从神奇的 绿色树蛇 项目及其所有贡献者那里改编的。
字面值¶
- class ast.Constant(value)¶
一个常量值。
Constant字面的value属性包含它所代表的 Python 对象。所代表的值可以是简单的类型,如数字、字符串或None,也可以是不可变的容器类型(tuple 和 frozenset),如果它们的所有元素都是常数的话。>>> 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持有代表其元素的节点列表。如果容器是一个赋值目标(即(x,y)=something),ctx是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()))], 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)¶
一个布尔运算,’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, starargs, kwargs)¶
一个函数调用。
func是函数,通常是一个Name或Attribute对象。参数:args持有一个由位置传递的参数列表。keywords持有一个keyword对象的列表,代表由 keyword 传递的参数。
当创建一个
Call节点时,args和keywords是必须的,但它们可以是空列表。starargs和kwargs是可选的。>>> print(ast.dump(ast.parse('func(a, b=c, *d, **e)', mode='eval'), indent=4)) Expression( body=Call( func=Name(id='func', ctx=Load()), args=[ Name(id='a', ctx=Load()), Starred( value=Name(id='d', ctx=Load()), ctx=Load())], keywords=[ keyword( arg='b', value=Name(id='c', ctx=Load())), keyword( value=Name(id='e', ctx=Load()))]))
- class ast.keyword(arg, value)¶
一个函数调用或类定义的关键字参数。
arg是参数名称的原始字符串,value是要传入的节点。
- class ast.IfExp(test, body, orelse)¶
一个表达式,如
a if b else c。每个字段持有一个节点,所以在下面的例子中,三个都是Name节点”>>> print(ast.dump(ast.parse('a if b else c', mode='eval'), indent=4)) Expression( body=IfExp( test=Name(id='b', ctx=Load()), body=Name(id='a', ctx=Load()), orelse=Name(id='c', ctx=Load())))
- class ast.Attribute(value, attr, ctx)¶
属性访问,例如:
d.keys。value是一个节点,通常是Name。attr是一个裸字符串,给出属性的名称,ctx是Load、Store或Del,根据属性的操作方式。>>> print(ast.dump(ast.parse('snake.colour', mode='eval'), indent=4)) Expression( body=Attribute( value=Name(id='snake', ctx=Load()), attr='colour', ctx=Load()))
- class ast.NamedExpr(target, value)¶
一个命名的表达式。这个 AST 节点是由赋值表达式运算符(也被称为海象运算符)产生的。相对于
Assign节点,其中第一个参数可以是多个节点,在这种情况下,target和value都必须是单个节点。>>> print(ast.dump(ast.parse('(x := 4)', mode='eval'), indent=4)) Expression( body=NamedExpr( target=Name(id='x', ctx=Store()), value=Constant(value=4)))
下标¶
- 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中的多个节点代表给每个节点分配相同的值。解包是通过在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))], 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是一个布尔整数,对于target中的Name节点,设置为 True,不出现在括号之间,因此是纯名称,不是表达式。>>> 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是一个Constant,值为 1。与
Assign的 targets 不同,target属性不能是Tuple或List类。>>> print(ast.dump(ast.parse('x += 2'), indent=4)) Module( body=[ AugAssign( target=Name(id='x', ctx=Store()), op=Add(), value=Constant(value=2))], type_ignores=[])
- class ast.Raise(exc, cause)¶
raise语句。exc是要引发的异常对象,通常是Call或Name,或None用于独立的raise。cause是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=[])
其他只适用于函数或循环内部的语句在其他章节中描述。
Imports¶
- class ast.Import(names)¶
导入语句。
names是一个alias节点的列表。>>> print(ast.dump(ast.parse('import x,y,z'), indent=4)) Module( body=[ Import( names=[ alias(name='x'), alias(name='y'), alias(name='z')])], type_ignores=[])
- class ast.ImportFrom(module, names, level)¶
代表
from x import y。module是 ‘from’ 名称的原始字符串,没有任何前导点,或None用于诸如from . foo的语句。level是一个整数,表示相对导入的级别(0 表示绝对导入)。>>> print(ast.dump(ast.parse('from y import x,y,z'), indent=4)) Module( body=[ ImportFrom( module='y', names=[ alias(name='x'), alias(name='y'), alias(name='z')], level=0)], type_ignores=[])
- class ast.alias(name, asname)¶
两个参数都是名字的原始字符串。如果要使用常规名称,
asname可以是None。>>> print(ast.dump(ast.parse('from ..foo.bar import a as b, c'), indent=4)) Module( body=[ ImportFrom( module='foo.bar', names=[ alias(name='a', asname='b'), alias(name='c')], level=2)], type_ignores=[])
控制流¶
备注
像 else 这样的可选子句,如果不存在,就会被存储为一个空列表。
- class ast.If(test, body, orelse)¶
if语句。test持有一个节点,例如Compare节点。body和orelse分别持有一个节点的列表。elif子句在 AST 中没有特殊的表示方法,而是作为额外的If节点出现在前一个子句的orelse部分。>>> print(ast.dump(ast.parse(""" ... if x: ... ... ... elif y: ... ... ... else: ... ... ... """), indent=4)) Module( body=[ If( test=Name(id='x', ctx=Load()), body=[ Expr( value=Constant(value=Ellipsis))], orelse=[ If( test=Name(id='y', ctx=Load()), body=[ Expr( value=Constant(value=Ellipsis))], orelse=[ Expr( value=Constant(value=Ellipsis))])])], type_ignores=[])
- class ast.For(target, iter, body, orelse, type_comment)¶
A
forloop.targetholds the variable(s) the loop assigns to, as a singleName,Tuple,List,AttributeorSubscriptnode.iterholds the item to be looped over, again as a single node.bodyandorelsecontain lists of nodes to execute. Those inorelseare executed if the loop finishes normally, rather than via abreakstatement.- 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)¶
tryblocks which are followed byexcept*clauses. The attributes are the same as forTrybut theExceptHandlernodes inhandlersare interpreted asexcept*blocks rather thenexcept.>>> 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=[])
- class ast.ExceptHandler(type, name, body)¶
一个单一的
except子句。type是它要匹配的异常类型,通常是Name节点(或者None是一个全面的except:子句)。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=[])
Pattern matching¶
- class ast.Match(subject, cases)¶
A
matchstatement.subjectholds the subject of the match (the object that is being matched against the cases) andcasescontains an iterable ofmatch_casenodes with the different cases.
- class ast.match_case(pattern, guard, body)¶
A single case pattern in a
matchstatement.patterncontains the match pattern that the subject will be matched against. Note that theASTnodes produced for patterns differ from those produced for expressions, even when they share the same syntax.The
guardattribute contains an expression that will be evaluated if the pattern matches the subject.bodycontains a list of nodes to execute if the pattern matches and the result of evaluating the guard expression is true.>>> print(ast.dump(ast.parse(""" ... match x: ... case [x] if x>0: ... ... ... case tuple(): ... ... ... """), indent=4)) Module( body=[ Match( subject=Name(id='x', ctx=Load()), cases=[ match_case( pattern=MatchSequence( patterns=[ MatchAs(name='x')]), guard=Compare( left=Name(id='x', ctx=Load()), ops=[ Gt()], comparators=[ Constant(value=0)]), body=[ Expr( value=Constant(value=Ellipsis))]), match_case( pattern=MatchClass( cls=Name(id='tuple', ctx=Load()), patterns=[], kwd_attrs=[], kwd_patterns=[]), body=[ Expr( value=Constant(value=Ellipsis))])])], type_ignores=[])
- class ast.MatchValue(value)¶
A match literal or value pattern that compares by equality.
valueis an expression node. Permitted value nodes are restricted as described in the match statement documentation. This pattern succeeds if the match subject is equal to the evaluated 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=[])
- class ast.MatchSingleton(value)¶
A match literal pattern that compares by identity.
valueis the singleton to be compared against:None,True, orFalse. This pattern succeeds if the match subject is the given constant.>>> print(ast.dump(ast.parse(""" ... match x: ... case None: ... ... ... """), indent=4)) Module( body=[ Match( subject=Name(id='x', ctx=Load()), cases=[ match_case( pattern=MatchSingleton(value=None), body=[ Expr( value=Constant(value=Ellipsis))])])], type_ignores=[])
- class ast.MatchSequence(patterns)¶
A match sequence pattern.
patternscontains the patterns to be matched against the subject elements if the subject is a sequence. Matches a variable length sequence if one of the subpatterns is aMatchStarnode, otherwise matches a fixed length sequence.>>> print(ast.dump(ast.parse(""" ... match x: ... case [1, 2]: ... ... ... """), indent=4)) Module( body=[ Match( subject=Name(id='x', ctx=Load()), cases=[ match_case( pattern=MatchSequence( patterns=[ MatchValue( value=Constant(value=1)), MatchValue( value=Constant(value=2))]), body=[ Expr( value=Constant(value=Ellipsis))])])], type_ignores=[])
- class ast.MatchStar(name)¶
Matches the rest of the sequence in a variable length match sequence pattern. If
nameis notNone, a list containing the remaining sequence elements is bound to that name if the overall sequence pattern is successful.>>> print(ast.dump(ast.parse(""" ... match x: ... case [1, 2, *rest]: ... ... ... case [*_]: ... ... ... """), indent=4)) Module( body=[ Match( subject=Name(id='x', ctx=Load()), cases=[ match_case( pattern=MatchSequence( patterns=[ MatchValue( value=Constant(value=1)), MatchValue( value=Constant(value=2)), MatchStar(name='rest')]), body=[ Expr( value=Constant(value=Ellipsis))]), match_case( pattern=MatchSequence( patterns=[ MatchStar()]), body=[ Expr( value=Constant(value=Ellipsis))])])], type_ignores=[])
- class ast.MatchMapping(keys, patterns, rest)¶
A match mapping pattern.
keysis a sequence of expression nodes.patternsis a corresponding sequence of pattern nodes.restis an optional name that can be specified to capture the remaining mapping elements. Permitted key expressions are restricted as described in the match statement documentation.This pattern succeeds if the subject is a mapping, all evaluated key expressions are present in the mapping, and the value corresponding to each key matches the corresponding subpattern. If
restis notNone, a dict containing the remaining mapping elements is bound to that name if the overall mapping pattern is successful.>>> print(ast.dump(ast.parse(""" ... match x: ... case {1: _, 2: _}: ... ... ... case {**rest}: ... ... ... """), indent=4)) Module( body=[ Match( subject=Name(id='x', ctx=Load()), cases=[ match_case( pattern=MatchMapping( keys=[ Constant(value=1), Constant(value=2)], patterns=[ MatchAs(), MatchAs()]), body=[ Expr( value=Constant(value=Ellipsis))]), match_case( pattern=MatchMapping(keys=[], patterns=[], rest='rest'), body=[ Expr( value=Constant(value=Ellipsis))])])], type_ignores=[])
- class ast.MatchClass(cls, patterns, kwd_attrs, kwd_patterns)¶
A match class pattern.
clsis an expression giving the nominal class to be matched.patternsis a sequence of pattern nodes to be matched against the class defined sequence of pattern matching attributes.kwd_attrsis a sequence of additional attributes to be matched (specified as keyword arguments in the class pattern),kwd_patternsare the corresponding patterns (specified as keyword values in the class pattern).This pattern succeeds if the subject is an instance of the nominated class, all positional patterns match the corresponding class-defined attributes, and any specified keyword attributes match their corresponding pattern.
Note: classes may define a property that returns self in order to match a pattern node against the instance being matched. Several builtin types are also matched that way, as described in the match statement documentation.
>>> print(ast.dump(ast.parse(""" ... match x: ... case Point2D(0, 0): ... ... ... case Point3D(x=0, y=0, z=0): ... ... ... """), indent=4)) Module( body=[ Match( subject=Name(id='x', ctx=Load()), cases=[ match_case( pattern=MatchClass( cls=Name(id='Point2D', ctx=Load()), patterns=[ MatchValue( value=Constant(value=0)), MatchValue( value=Constant(value=0))], kwd_attrs=[], kwd_patterns=[]), body=[ Expr( value=Constant(value=Ellipsis))]), match_case( pattern=MatchClass( cls=Name(id='Point3D', ctx=Load()), patterns=[], kwd_attrs=[ 'x', 'y', 'z'], kwd_patterns=[ MatchValue( value=Constant(value=0)), MatchValue( value=Constant(value=0)), MatchValue( value=Constant(value=0))]), body=[ Expr( value=Constant(value=Ellipsis))])])], type_ignores=[])
- class ast.MatchAs(pattern, name)¶
A match “as-pattern”, capture pattern or wildcard pattern.
patterncontains the match pattern that the subject will be matched against. If the pattern isNone, the node represents a capture pattern (i.e a bare name) and will always succeed.The
nameattribute contains the name that will be bound if the pattern is successful. IfnameisNone,patternmust also beNoneand the node represents the wildcard pattern.>>> print(ast.dump(ast.parse(""" ... match x: ... case [x] as y: ... ... ... case _: ... ... ... """), indent=4)) Module( body=[ Match( subject=Name(id='x', ctx=Load()), cases=[ match_case( pattern=MatchAs( pattern=MatchSequence( patterns=[ MatchAs(name='x')]), name='y'), body=[ Expr( value=Constant(value=Ellipsis))]), match_case( pattern=MatchAs(), body=[ Expr( value=Constant(value=Ellipsis))])])], type_ignores=[])
- class ast.MatchOr(patterns)¶
A match “or-pattern”. An or-pattern matches each of its subpatterns in turn to the subject, until one succeeds. The or-pattern is then deemed to succeed. If none of the subpatterns succeed the or-pattern fails. The
patternsattribute contains a list of match pattern nodes that will be matched against the subject.>>> 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=[])
Function and class definitions¶
- class ast.FunctionDef(name, args, body, decorator_list, returns, type_comment)¶
A function definition.
nameis a raw string of the function name.argsis anargumentsnode.bodyis the list of nodes inside the function.decorator_listis the list of decorators to be applied, stored outermost first (i.e. the first in the list will be applied last).returnsis the return annotation.
- type_comment¶
type_comment是一个可选的字符串,其中的类型注释是一个注释。
- class ast.Lambda(args, body)¶
lambdais a minimal function definition that can be used inside an expression. UnlikeFunctionDef,bodyholds a single node.>>> 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)¶
The arguments for a function.
posonlyargs,argsandkwonlyargsare lists ofargnodes.varargandkwargare singleargnodes, referring to the*args, **kwargsparameters.kw_defaultsis a list of default values for keyword-only arguments. If one isNone, the corresponding argument is required.defaultsis a list of default values for arguments that can be passed positionally. If there are fewer defaults, they correspond to the last n arguments.
- class ast.arg(arg, annotation, type_comment)¶
A single argument in a list.
argis a raw string of the argument name,annotationis its annotation, such as aStrorNamenode.- type_comment¶
type_commentis an optional string with the type annotation as a comment
>>> print(ast.dump(ast.parse("""\ ... @decorator1 ... @decorator2 ... def f(a: 'annotation', b=1, c=2, *d, e, f=3, **g) -> 'return annotation': ... pass ... """), indent=4)) Module( body=[ FunctionDef( name='f', args=arguments( posonlyargs=[], args=[ arg( arg='a', annotation=Constant(value='annotation')), arg(arg='b'), arg(arg='c')], vararg=arg(arg='d'), kwonlyargs=[ arg(arg='e'), arg(arg='f')], kw_defaults=[ None, Constant(value=3)], kwarg=arg(arg='g'), defaults=[ Constant(value=1), Constant(value=2)]), body=[ Pass()], decorator_list=[ Name(id='decorator1', ctx=Load()), Name(id='decorator2', ctx=Load())], returns=Constant(value='return annotation'))], type_ignores=[])
- class ast.Return(value)¶
A
returnstatement.>>> 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)¶
A
yieldoryield fromexpression. Because these are expressions, they must be wrapped in aExprnode if the value sent back is not used.>>> 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)¶
globalandnonlocalstatements.namesis a list of raw strings.>>> print(ast.dump(ast.parse('global x,y,z'), indent=4)) Module( body=[ Global( names=[ 'x', 'y', 'z'])], type_ignores=[]) >>> print(ast.dump(ast.parse('nonlocal x,y,z'), indent=4)) Module( body=[ Nonlocal( names=[ 'x', 'y', 'z'])], type_ignores=[])
- class ast.ClassDef(name, bases, keywords, starargs, kwargs, body, decorator_list)¶
A class definition.
nameis a raw string for the class namebasesis a list of nodes for explicitly specified base classes.keywordsis a list ofkeywordnodes, principally for ‘metaclass’. Other keywords will be passed to the metaclass, as per PEP-3115.starargsandkwargsare each a single node, as in a function call. starargs will be expanded to join the list of base classes, and kwargs will be passed to the metaclass.bodyis a list of nodes representing the code within the class definition.decorator_listis a list of nodes, as inFunctionDef.
>>> print(ast.dump(ast.parse("""\ ... @decorator1 ... @decorator2 ... class Foo(base1, base2, metaclass=meta): ... pass ... """), indent=4)) Module( body=[ ClassDef( name='Foo', bases=[ Name(id='base1', ctx=Load()), Name(id='base2', ctx=Load())], keywords=[ keyword( arg='metaclass', value=Name(id='meta', ctx=Load()))], body=[ Pass()], decorator_list=[ Name(id='decorator1', ctx=Load()), Name(id='decorator2', ctx=Load())])], type_ignores=[])
Async and await¶
- class ast.AsyncFunctionDef(name, args, body, decorator_list, returns, type_comment)¶
An
async deffunction definition. Has the same fields asFunctionDef.
- class ast.Await(value)¶
An
awaitexpression.valueis what it waits for. Only valid in the body of anAsyncFunctionDef.
>>> print(ast.dump(ast.parse("""\
... async def f():
... await other_func()
... """), indent=4))
Module(
body=[
AsyncFunctionDef(
name='f',
args=arguments(
posonlyargs=[],
args=[],
kwonlyargs=[],
kw_defaults=[],
defaults=[]),
body=[
Expr(
value=Await(
value=Call(
func=Name(id='other_func', ctx=Load()),
args=[],
keywords=[])))],
decorator_list=[])],
type_ignores=[])
- class ast.AsyncFor(target, iter, body, orelse, type_comment)¶
- class ast.AsyncWith(items, body, type_comment)¶
async forloops andasync withcontext managers. They have the same fields asForandWith, respectively. Only valid in the body of anAsyncFunctionDef.
备注
When a string is parsed by ast.parse(), operator nodes (subclasses
of ast.operator, ast.unaryop, ast.cmpop,
ast.boolop and ast.expr_context) on the returned tree
will be singletons. Changes to one will be reflected in all other
occurrences of the same value (e.g. ast.Add).
ast 中的辅助工具¶
除了节点类, ast 模块里为遍历抽象语法树定义了这些工具函数和类:
- ast.parse(source, filename='<unknown>', mode='exec', *, type_comments=False, feature_version=None)¶
把 source 解析为 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 版本的语法进行解析。目前major必须等于3。例如,设置feature_version=(3, 4)将允许使用async和await作为变量名。支持的最低版本是(3, 4);最高版本是sys.version_info[0:2]。如果 source 包含一个空字符(’0’),
ValueError将被触发。警告
注意,成功地将源代码解析成 AST 对象并不保证所提供的源代码是可以执行的有效 Python 代码,因为编译步骤可能会引发进一步的
SyntaxError异常。例如,源码return 42为返回语句生成了一个有效的 AST 节点,但它不能被单独编译(它需要在一个函数节点内)。特别是,
ast.parse()不会做任何范围检查,而编译步骤会做。警告
足够复杂或是巨大的字符串可能导致 Python 解释器的崩溃,因为 Python 的 AST 编译器是有栈深限制的。
在 3.8 版更改: 增加了
type_comments、mode='func_type'和feature_version。
- ast.unparse(ast_obj)¶
反向解析
ast.AST对象,并生成一个字符串,如果用ast.parse()解析,将产生一个等价的ast.AST对象的代码。警告
产生的代码字符串不一定等于产生
ast.AST对象的原始代码(没有任何编译器优化,如常数 tuple/frozenset)。警告
试图解读一个高度复杂的表达式会导致
RecursionError。3.9 新版功能.
- ast.literal_eval(node_or_string)¶
Evaluate an expression node or a string containing only a Python literal or container display. The string or node provided may only consist of the following Python literal structures: strings, bytes, numbers, tuples, lists, dicts, sets, booleans,
NoneandEllipsis.This can be used for evaluating strings containing Python values without the need to parse the values oneself. It is not capable of evaluating arbitrarily complex expressions, for example involving operators or indexing.
This function had been documented as “safe” in the past without defining what that meant. That was misleading. This is specifically designed not to execute Python code, unlike the more general
eval(). There is no namespace, no name lookups, or ability to call out. But it is not free from attack: A relatively small input can lead to memory exhaustion or to C stack exhaustion, crashing the process. There is also the possibility for excessive CPU consumption denial of service on some inputs. Calling it on untrusted data is thus not recommended.警告
It is possible to crash the Python interpreter due to stack depth limitations in Python’s AST compiler.
它可能引发
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 为真,则用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)¶
如果可能的话,从 old_node 复制源位置(
lineno、col_offset、end_lineno和end_col_offset)到 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()或自己访问它们。
如果你想在遍历过程中对节点进行修改,请不要使用
NodeVisitor。为此,存在一个特殊的访问者(NodeTransformer),允许修改。3.8 版后已移除: 方法
visit_Num()、visit_Str()、visit_Bytes()、visit_NameConstant()和visit_Ellipsis()现在已经废弃,在未来的 Python 版本中不会被调用。添加visit_Constant()方法来处理所有常数节点。
- class ast.NodeTransformer¶
子类
NodeVisitor用于遍历抽象语法树,并允许修改节点。NodeTransformer将遍历抽象语法树并使用visitor方法的返回值去替换或移除旧节点。如果visitor方法的返回值为None, 则该节点将从其位置移除,否则将替换为返回值。当返回值是原始节点时,无需替换。如下是一个转换器示例,它将所有出现的名称 (
foo) 重写为data['foo']:class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load()), slice=Constant(value=node.id), ctx=node.ctx )
请记住,如果您正在操作的节点具有子节点,则必须先转换其子节点或为该节点调用
generic_visit()方法。对于属于语句集合(适用于所有语句节点)的节点,访问者还可以返回节点列表而不仅仅是单个节点。
如果
NodeTransformer引入了新的节点(不是原来树的一部分),而没有给它们位置信息(比如lineno),那么fix_missing_locations()应该与新的子树一起调用,以重新计算位置信息tree = ast.parse('foo', mode='eval') new_tree = fix_missing_locations(RewriteName().visit(tree))
通常你可以像这样使用转换器
node = YourTransformer().visit(node)
- ast.dump(node, annotate_fields=True, include_attributes=False, *, indent=None)¶
返回 node 中树的格式化转储。这主要是为了调试的目的。如果 annotate_fields 为 true(默认),返回的字符串将显示字段的名称和值。如果 annotate_fields 为 false,结果字符串将通过省略不明确的字段名而变得更加紧凑。默认情况下,诸如行号和列的偏移量等属性不会被转储。如果希望这样,可以将 include_attributes 设置为 true。
如果 indent 是一个非负的整数或字符串,那么树就会以该缩进级别进行漂亮的打印。缩进级别为 0、负数或
""将只插入新行。None(默认)选择单行表示法。使用正的整数缩进,每一级有那么多的空格。如果 indent 是一个字符串(如"\t"),该字符串将用于缩进每一级。在 3.9 版更改: 添加 indent 选项。
Compiler Flags¶
The following flags may be passed to compile() in order to change
effects on the compilation of a program:
- ast.PyCF_ALLOW_TOP_LEVEL_AWAIT¶
Enables support for top-level
await,async for,async withand async comprehensions.3.8 新版功能.
- ast.PyCF_ONLY_AST¶
Generates and returns an abstract syntax tree instead of returning a compiled code object.
命令行用法¶
3.9 新版功能.
The ast module can be executed as a script from the command line.
It is as simple as:
python -m ast [-m <mode>] [-a] [infile]
可以接受以下选项:
- -h, --help¶
Show the help message and exit.
- -m <mode>¶
- --mode <mode>¶
Specify what kind of code must be compiled, like the mode argument in
parse().
- --no-type-comments¶
Don’t parse type comments.
- -a, --include-attributes¶
Include attributes such as line numbers and column offsets.
If infile is specified its contents are parsed to AST and dumped
to stdout. Otherwise, the content is read from stdin.
参见
Green Tree Snakes, an external documentation resource, has good details on working with Python ASTs.
ASTTokens annotates Python ASTs with the positions of tokens and text in the source code that generated them. This is helpful for tools that make source code transformations.
leoAst.py unifies the token-based and parse-tree-based views of python programs by inserting two-way links between tokens and ast nodes.
LibCST parses code as a Concrete Syntax Tree that looks like an ast tree and keeps all formatting details. It’s useful for building automated refactoring (codemod) applications and linters.
Parso is a Python parser that supports error recovery and round-trip parsing for different Python versions (in multiple Python versions). Parso is also able to list multiple syntax errors in your python file.