ast — 抽象语法树 — Python 文档
ast — 抽象语法树
源代码: :source:`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)
| Assert(expr test, expr? msg)
| Import(alias* names)
| ImportFrom(identifier? module, alias* names, int? level)
| Global(identifier* names)
| Nonlocal(identifier* names)
| Expr(expr value)
| Pass | Break | Continue
-- col_offset is the byte offset in the utf8 string the parser uses
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
-- BoolOp() can use left & right?
expr = BoolOp(boolop op, expr* values)
| NamedExpr(expr target, expr value)
| BinOp(expr left, operator op, expr right)
| UnaryOp(unaryop op, expr operand)
| Lambda(arguments args, expr body)
| IfExp(expr test, expr body, expr orelse)
| Dict(expr* keys, expr* values)
| Set(expr* elts)
| ListComp(expr elt, comprehension* generators)
| SetComp(expr elt, comprehension* generators)
| DictComp(expr key, expr value, comprehension* generators)
| GeneratorExp(expr elt, comprehension* generators)
-- the grammar constrains where yield expressions can occur
| Await(expr value)
| Yield(expr? value)
| YieldFrom(expr value)
-- need sequences for compare to distinguish between
-- x < 4 < 3 and (x < 4) < 3
| Compare(expr left, cmpop* ops, expr* comparators)
| Call(expr func, expr* args, keyword* keywords)
| FormattedValue(expr value, int? conversion, expr? format_spec)
| JoinedStr(expr* values)
| Constant(constant value, string? kind)
-- the following expression can appear in assignment context
| Attribute(expr value, identifier attr, expr_context ctx)
| Subscript(expr value, expr slice, expr_context ctx)
| Starred(expr value, expr_context ctx)
| Name(identifier id, expr_context ctx)
| List(expr* elts, expr_context ctx)
| Tuple(expr* elts, expr_context ctx)
-- can appear only in Subscript
| Slice(expr? lower, expr? upper, expr? step)
-- col_offset is the byte offset in the utf8 string the parser uses
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
expr_context = Load | Store | Del
boolop = And | Or
operator = Add | Sub | Mult | MatMult | Div | Mod | Pow | LShift
| RShift | BitOr | BitXor | BitAnd | FloorDiv
unaryop = Invert | Not | UAdd | USub
cmpop = Eq | NotEq | Lt | LtE | Gt | GtE | Is | IsNot | In | NotIn
comprehension = (expr target, expr iter, expr* ifs, int is_async)
excepthandler = ExceptHandler(expr? type, identifier? name, stmt* body)
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
arguments = (arg* posonlyargs, arg* args, arg? vararg, arg* kwonlyargs,
expr* kw_defaults, arg? kwarg, expr* defaults)
arg = (identifier arg, expr? annotation, string? type_comment)
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
-- keyword arguments supplied to call (NULL identifier for **kwargs)
keyword = (identifier? arg, expr value)
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
-- import name with optional 'as' alias.
alias = (identifier name, identifier? asname)
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
withitem = (expr context_expr, expr? optional_vars)
match_case = (pattern pattern, expr? guard, stmt* body)
pattern = MatchValue(expr value)
| MatchSingleton(constant value)
| MatchSequence(pattern* patterns)
| MatchMapping(expr* keys, pattern* patterns, identifier? rest)
| MatchClass(expr cls, pattern* patterns, identifier* kwd_attrs, pattern* kwd_patterns)
| MatchStar(identifier? name)
-- The optional "rest" MatchMapping parameter handles capturing extra mapping keys
| MatchAs(pattern? pattern, identifier? name)
| MatchOr(pattern* patterns)
attributes (int lineno, int col_offset, int end_lineno, int end_col_offset)
type_ignore = TypeIgnore(int lineno, string tag)
}
节点类
- class ast.AST
这是所有 AST 节点类的基础。 实际的节点类派生自
Parser/Python.asdl
文件,该文件在 下面复制 。 它们在_ast
C 模块中定义并在 ast 中重新导出。为抽象语法中的每个左侧符号定义了一个类(例如,
ast.stmt
或ast.expr
)。 此外,右侧为每个构造函数定义了一个类; 这些类继承自左侧树的类。 例如,ast.BinOp 继承自ast.expr
。 对于带有替代项(又名“总和”)的产生式规则,左侧的类是抽象的:只创建特定构造函数节点的实例。- _fields
每个具体类都有一个属性 _fields,它给出了所有子节点的名称。
具体类的每个实例的每个子节点都有一个属性,其类型在语法中定义。 例如,ast.BinOp 实例具有
ast.expr
类型的属性left
。如果这些属性在语法中标记为可选(使用问号),则值可能是
None
。 如果属性可以有零个或多个值(用星号标记),则这些值表示为 Python 列表。 使用 compile() 编译 AST 时,所有可能的属性都必须存在并具有有效值。
- lineno
col_offset
end_lineno
end_col_offset ast.expr
和ast.stmt
子类的实例具有 lineno、col_offset、end_lineno 和 end_col_offset] 属性. lineno 和 end_lineno 是源文本跨度的第一个和最后一个行号(1 索引,所以第一行是第 1 行)和 col_offset 和 [ X172X]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 版更改:Class 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
,也可以是不可变的容器类型(元组和frozensets),如果它们的所有元素都是常量。>>> print(ast.dump(ast.parse('123', mode='eval'), indent=4)) Expression( body=Constant(value=123))
- class ast.FormattedValue(value, conversion, format_spec)
- 代表 f 字符串中单个格式字段的节点。 如果字符串包含单个格式字段并且没有其他任何内容,则该节点可以被隔离,否则它会出现在 JoinedStr 中。
value
是任何表达式节点(例如文字、变量或函数调用)。conversion
是一个整数:
- -1:无格式
- 115:
!s
字符串格式 - 114:
!r
repr 格式 - 97:
!a
ascii 格式
format_spec
是一个 JoinedStr 节点,表示值的格式,如果没有指定格式,则为None
。conversion
和format_spec
可以同时设置。
- class ast.JoinedStr(values)
一个 f 字符串,包括一系列 FormattedValue 和 Constant 节点。
>>> print(ast.dump(ast.parse('f"sin({a}) is {sin(a):.3}"', mode='eval'), indent=4)) Expression( body=JoinedStr( values=[ Constant(value='sin('), FormattedValue( value=Name(id='a', ctx=Load()), conversion=-1), Constant(value=') is '), FormattedValue( value=Call( func=Name(id='sin', ctx=Load()), args=[ Name(id='a', ctx=Load())], keywords=[]), conversion=-1, format_spec=JoinedStr( values=[ Constant(value='.3')]))]))
- class ast.List(elts, ctx)
class ast.Tuple(elts, ctx) 列表或元组。
elts
保存代表元素的节点列表。ctx
是 Store 如果容器是分配目标(即(x,y)=something
) 和 Load 否则。>>> print(ast.dump(ast.parse('[1, 2, 3]', mode='eval'), indent=4)) Expression( body=List( elts=[ Constant(value=1), Constant(value=2), Constant(value=3)], ctx=Load())) >>> print(ast.dump(ast.parse('(1, 2, 3)', mode='eval'), indent=4)) Expression( body=Tuple( elts=[ Constant(value=1), Constant(value=2), Constant(value=3)], ctx=Load()))
- class ast.Set(elts)
一套。
elts
保存一个代表集合元素的节点列表。>>> print(ast.dump(ast.parse('{1, 2, 3}', mode='eval'), indent=4)) Expression( body=Set( elts=[ Constant(value=1), Constant(value=2), Constant(value=3)]))
- class ast.Dict(keys, values)
一本字典。
keys
和values
按匹配顺序分别保存表示键和值的节点列表(调用dictionary.keys()
和dictionary.values()
时将返回什么)。当使用字典字面量进行字典解包时,要扩展的表达式在
values
列表中,在keys
中的相应位置有一个None
。>>> print(ast.dump(ast.parse('{"a":1, **d}', mode='eval'), indent=4)) Expression( body=Dict( keys=[ Constant(value='a'), None], values=[ Constant(value=1), Name(id='d', ctx=Load())]))
变量
- class ast.Name(id, ctx)
- 一个变量名。
id
将名称保存为字符串,ctx
是以下类型之一。
- class ast.Load
class ast.Store
class ast.Del 变量引用可用于加载变量的值、为其分配新值或删除它。 变量引用被赋予一个上下文来区分这些情况。
>>> print(ast.dump(ast.parse('a'), indent=4)) Module( body=[ Expr( value=Name(id='a', ctx=Load()))], type_ignores=[]) >>> print(ast.dump(ast.parse('a = 1'), indent=4)) Module( body=[ Assign( targets=[ Name(id='a', ctx=Store())], value=Constant(value=1))], type_ignores=[]) >>> print(ast.dump(ast.parse('del a'), indent=4)) Module( body=[ Delete( targets=[ Name(id='a', ctx=Del())])], type_ignores=[])
- class ast.Starred(value, ctx)
*var
变量引用。value
保存变量,通常是一个 Name 节点。 使用*args
构建 Call 节点时必须使用此类型。>>> print(ast.dump(ast.parse('a, *b = it'), indent=4)) Module( body=[ Assign( targets=[ Tuple( elts=[ Name(id='a', ctx=Store()), Starred( value=Name(id='b', ctx=Store()), ctx=Store())], ctx=Store())], value=Name(id='it', ctx=Load()))], type_ignores=[])
表达式
- class ast.Expr(value)
当一个表达式(如函数调用)作为一个单独的语句出现而其返回值未被使用或存储时,它被包装在这个容器中。
value
持有本节中的其他节点之一,一个 Constant,一个 Name,一个 Lambda,一个 Yield ] 或 YieldFrom 节点。>>> print(ast.dump(ast.parse('-a'), indent=4)) Module( body=[ Expr( value=UnaryOp( op=USub(), operand=Name(id='a', ctx=Load())))], type_ignores=[])
- class ast.UnaryOp(op, operand)
- 一元运算。
op
是操作符,operand
是任何表达式节点。
- class ast.UAdd
class ast.USub
class ast.Not
class ast.Invert 一元运算符令牌。 Not 是
not
关键字,Invert 是~
运算符。>>> print(ast.dump(ast.parse('not x', mode='eval'), indent=4)) Expression( body=UnaryOp( op=Not(), operand=Name(id='x', ctx=Load())))
- class ast.BinOp(left, op, right)
二元运算(如加法或除法)。
op
是运算符,left
和right
是任何表达式节点。>>> print(ast.dump(ast.parse('x + y', mode='eval'), indent=4)) Expression( body=BinOp( left=Name(id='x', ctx=Load()), op=Add(), right=Name(id='y', ctx=Load())))
- class ast.Add
class ast.Sub
class ast.Mult
class ast.Div
class ast.FloorDiv
class ast.Mod
class ast.Pow
class ast.LShift
class ast.RShift
class ast.BitOr
class ast.BitXor
class ast.BitAnd
class ast.MatMult
- 二元运算符令牌。
- class ast.BoolOp(op, values)
布尔运算,“或”或“与”。
op
是 或 或 和 。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.And
class ast.Or
- 布尔运算符标记。
- class ast.Compare(left, ops, comparators)
两个或多个值的比较。
left
是比较中的第一个值,ops
是运算符列表,comparators
是比较中第一个元素之后的值列表。>>> print(ast.dump(ast.parse('1 <= a < 10', mode='eval'), indent=4)) Expression( body=Compare( left=Constant(value=1), ops=[ LtE(), Lt()], comparators=[ Name(id='a', ctx=Load()), Constant(value=10)]))
- class ast.Eq
class ast.NotEq
class ast.Lt
class ast.LtE
class ast.Gt
class ast.GtE
class ast.Is
class ast.IsNot
class ast.In
class ast.NotIn
- 比较运算符标记。
- class ast.Call(func, args, keywords, starargs, kwargs)
一个函数调用。
func
是函数,通常是 Name 或 Attribute 对象。 论据:args
保存按位置传递的参数列表。keywords
保存了一个 keyword 对象列表,表示关键字传递的参数。
创建
Call
节点时,需要args
和keywords
,但可以是空列表。starargs
和kwargs
是可选的。>>> print(ast.dump(ast.parse('func(a, b=c, *d, **e)', mode='eval'), indent=4)) Expression( body=Call( func=Name(id='func', ctx=Load()), args=[ Name(id='a', ctx=Load()), Starred( value=Name(id='d', ctx=Load()), ctx=Load())], keywords=[ keyword( arg='b', value=Name(id='c', ctx=Load())), keyword( value=Name(id='e', ctx=Load()))]))
- class ast.keyword(arg, value)
- 函数调用或类定义的关键字参数。
arg
是参数名的原始字符串,value
是要传入的节点。
- class ast.IfExp(test, body, orelse)
一个表达式,例如
a if b else c
。 每个字段包含一个节点,因此在以下示例中,所有三个都是 Name 节点。>>> print(ast.dump(ast.parse('a if b else c', mode='eval'), indent=4)) Expression( body=IfExp( test=Name(id='b', ctx=Load()), body=Name(id='a', ctx=Load()), orelse=Name(id='c', ctx=Load())))
- class ast.Attribute(value, attr, ctx)
属性访问,例如
d.keys
。value
是一个节点,通常是一个 Name。attr
是给出属性名称的裸字符串,ctx
是 Load、Store 或 Del如何作用于属性。>>> print(ast.dump(ast.parse('snake.colour', mode='eval'), indent=4)) Expression( body=Attribute( value=Name(id='snake', ctx=Load()), attr='colour', ctx=Load()))
- class ast.NamedExpr(target, value)
命名表达式。 该 AST 节点由赋值表达式运算符(也称为 walrus 运算符)生成。 与第一个参数可以是多个节点的 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
是索引、切片或键。 它可以是 元组 并包含 切片 。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
是一个 常数 ,值为 1。target
属性不能是 Tuple 或 List 类,与 Assign 的目标不同。>>> print(ast.dump(ast.parse('x += 2'), indent=4)) Module( body=[ AugAssign( target=Name(id='x', ctx=Store()), op=Add(), value=Constant(value=2))], type_ignores=[])
- class ast.Raise(exc, cause)
raise
语句。exc
是要引发的异常对象,通常是 Call 或 Name,或None
用于独立的raise
。cause
是raise x from y
中y
的可选部分。>>> print(ast.dump(ast.parse('raise x from y'), indent=4)) Module( body=[ Raise( exc=Name(id='x', ctx=Load()), cause=Name(id='y', ctx=Load()))], type_ignores=[])
- class ast.Assert(test, msg)
一个断言。
test
保存条件,例如 Compare 节点。msg
保存失败信息。>>> print(ast.dump(ast.parse('assert x,y'), indent=4)) Module( body=[ Assert( test=Name(id='x', ctx=Load()), msg=Name(id='y', ctx=Load()))], type_ignores=[])
- class ast.Delete(targets)
表示
del
语句。targets
是节点列表,例如 Name、Attribute 或 Subscript 节点。>>> print(ast.dump(ast.parse('del x,y,z'), indent=4)) Module( body=[ Delete( targets=[ Name(id='x', ctx=Del()), Name(id='y', ctx=Del()), Name(id='z', ctx=Del())])], type_ignores=[])
- class ast.Pass
pass
语句。>>> print(ast.dump(ast.parse('pass'), indent=4)) Module( body=[ Pass()], type_ignores=[])
其他部分描述了仅适用于函数或循环内部的其他语句。
进口
- class ast.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
是“来自”名称的原始字符串,没有任何前导点,或None
用于诸如from . import foo
之类的语句。level
是一个整数,表示相对导入的级别(0 表示绝对导入)。>>> print(ast.dump(ast.parse('from y import x,y,z'), indent=4)) Module( body=[ ImportFrom( module='y', names=[ alias(name='x'), alias(name='y'), alias(name='z')], level=0)], type_ignores=[])
- class ast.alias(name, asname)
这两个参数都是名称的原始字符串。 如果要使用常规名称,
asname
可以是None
。>>> print(ast.dump(ast.parse('from ..foo.bar import a as b, c'), indent=4)) Module( body=[ ImportFrom( module='foo.bar', names=[ alias(name='a', asname='b'), alias(name='c')], level=2)], type_ignores=[])
控制流
笔记
诸如 else
之类的可选子句如果不存在则存储为空列表。
- class ast.If(test, body, orelse)
if
语句。test
保存单个节点,例如 Compare 节点。body
和orelse
各持有一个节点列表。elif
子句在 AST 中没有特殊表示,而是在前一个的orelse
部分中作为额外的 If 节点出现。>>> print(ast.dump(ast.parse(""" ... if x: ... ... ... elif y: ... ... ... else: ... ... ... """), indent=4)) Module( body=[ If( test=Name(id='x', ctx=Load()), body=[ Expr( value=Constant(value=Ellipsis))], orelse=[ If( test=Name(id='y', ctx=Load()), body=[ Expr( value=Constant(value=Ellipsis))], orelse=[ Expr( value=Constant(value=Ellipsis))])])], type_ignores=[])
- class ast.For(target, iter, body, orelse, type_comment)
for
循环。target
保存循环分配给的变量,作为单个 Name、Tuple 或 List 节点。iter
保存要循环的项目,再次作为单个节点。body
和orelse
包含要执行的节点列表。 如果循环正常结束,则执行orelse
中的那些,而不是通过break
语句。- type_comment
type_comment
是一个可选字符串,带有类型注释作为注释。
>>> print(ast.dump(ast.parse(""" ... for x in y: ... ... ... else: ... ... ... """), indent=4)) Module( body=[ For( target=Name(id='x', ctx=Store()), iter=Name(id='y', ctx=Load()), body=[ Expr( value=Constant(value=Ellipsis))], orelse=[ Expr( value=Constant(value=Ellipsis))])], type_ignores=[])
- class ast.While(test, body, orelse)
while
循环。test
保存条件,例如 Compare 节点。>> print(ast.dump(ast.parse(""" ... while x: ... ... ... else: ... ... ... """), indent=4)) Module( body=[ While( test=Name(id='x', ctx=Load()), body=[ Expr( value=Constant(value=Ellipsis))], orelse=[ Expr( value=Constant(value=Ellipsis))])], type_ignores=[])
- class ast.Break
class ast.Continue break
和continue
语句。>>> print(ast.dump(ast.parse("""\ ... for a in b: ... if a > 5: ... break ... else: ... continue ... ... """), indent=4)) Module( body=[ For( target=Name(id='a', ctx=Store()), iter=Name(id='b', ctx=Load()), body=[ If( test=Compare( left=Name(id='a', ctx=Load()), ops=[ Gt()], comparators=[ Constant(value=5)]), body=[ Break()], orelse=[ Continue()])], orelse=[])], type_ignores=[])
- class ast.Try(body, handlers, orelse, finalbody)
try
块。 所有属性都是要执行的节点列表,除了handlers
,它是 ExceptHandler 节点的列表。>>> print(ast.dump(ast.parse(""" ... try: ... ... ... except Exception: ... ... ... except OtherException as e: ... ... ... else: ... ... ... finally: ... ... ... """), indent=4)) Module( body=[ Try( body=[ Expr( value=Constant(value=Ellipsis))], handlers=[ ExceptHandler( type=Name(id='Exception', ctx=Load()), body=[ Expr( value=Constant(value=Ellipsis))]), ExceptHandler( type=Name(id='OtherException', ctx=Load()), name='e', body=[ Expr( value=Constant(value=Ellipsis))])], orelse=[ Expr( value=Constant(value=Ellipsis))], finalbody=[ Expr( value=Constant(value=Ellipsis))])], type_ignores=[])
- class ast.ExceptHandler(type, name, body)
单个
except
子句。type
是它将匹配的异常类型,通常是 Name 节点(或None
用于全面except:
子句)。name
是用于保存异常的名称的原始字符串,如果子句没有as foo
,则为None
。body
是节点列表。>>> print(ast.dump(ast.parse("""\ ... try: ... a + 1 ... except TypeError: ... pass ... """), indent=4)) Module( body=[ Try( body=[ Expr( value=BinOp( left=Name(id='a', ctx=Load()), op=Add(), right=Constant(value=1)))], handlers=[ ExceptHandler( type=Name(id='TypeError', ctx=Load()), body=[ Pass()])], orelse=[], finalbody=[])], type_ignores=[])
- class ast.With(items, body, type_comment)
with
块。items
是一个 withitem 节点的列表,代表上下文管理器,body
是上下文内的缩进块。
- type_comment
type_comment
是一个可选字符串,带有类型注释作为注释。
- class ast.withitem(context_expr, optional_vars)
with
块中的单个上下文管理器。context_expr
是上下文管理器,通常是一个 Call 节点。optional_vars
是 Name、Tuple 或 List 对于as foo
部分,或None
没有使用。>>> print(ast.dump(ast.parse("""\ ... with a as b, c as d: ... something(b, d) ... """), indent=4)) Module( body=[ With( items=[ withitem( context_expr=Name(id='a', ctx=Load()), optional_vars=Name(id='b', ctx=Store())), withitem( context_expr=Name(id='c', ctx=Load()), optional_vars=Name(id='d', ctx=Store()))], body=[ Expr( value=Call( func=Name(id='something', ctx=Load()), args=[ Name(id='b', ctx=Load()), Name(id='d', ctx=Load())], keywords=[]))])], type_ignores=[])
模式匹配
- class ast.Match(subject, cases)
match
语句。subject
包含匹配的主题(与案例匹配的对象),cases
包含具有不同案例的 match_case 节点的迭代。
- 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()), patterns=[], kwd_attrs=[], kwd_patterns=[]), body=[ Expr( value=Constant(value=Ellipsis))])])], type_ignores=[])
- class ast.MatchValue(value)
按相等进行比较的匹配文字或值模式。
value
是一个表达式节点。 如匹配语句文档中所述,允许的值节点受到限制。 如果匹配主题等于评估值,则此模式成功。>>> print(ast.dump(ast.parse(""" ... match x: ... case "Relevant": ... ... ... """), indent=4)) Module( body=[ Match( subject=Name(id='x', ctx=Load()), cases=[ match_case( pattern=MatchValue( value=Constant(value='Relevant')), body=[ Expr( value=Constant(value=Ellipsis))])])], type_ignores=[])
- class ast.MatchSingleton(value)
按标识进行比较的匹配文字模式。
value
是要与以下对象进行比较的单例:None
、True
或False
。 如果匹配主题是给定的常量,则此模式成功。>>> print(ast.dump(ast.parse(""" ... match x: ... case None: ... ... ... """), indent=4)) Module( body=[ Match( subject=Name(id='x', ctx=Load()), cases=[ match_case( pattern=MatchSingleton(value=None), body=[ Expr( value=Constant(value=Ellipsis))])])], type_ignores=[])
- class ast.MatchSequence(patterns)
匹配序列模式。
patterns
包含要与主题元素匹配的模式,如果主题是一个序列。 如果子模式之一是MatchStar
节点,则匹配可变长度序列,否则匹配固定长度序列。>>> print(ast.dump(ast.parse(""" ... match x: ... case [1, 2]: ... ... ... """), indent=4)) Module( body=[ Match( subject=Name(id='x', ctx=Load()), cases=[ match_case( pattern=MatchSequence( patterns=[ MatchValue( value=Constant(value=1)), MatchValue( value=Constant(value=2))]), body=[ Expr( value=Constant(value=Ellipsis))])])], type_ignores=[])
- class ast.MatchStar(name)
以可变长度匹配序列模式匹配序列的其余部分。 如果
name
不是None
,如果整个序列模式成功,则包含剩余序列元素的列表将绑定到该名称。>>> print(ast.dump(ast.parse(""" ... match x: ... case [1, 2, *rest]: ... ... ... case [*_]: ... ... ... """), indent=4)) Module( body=[ Match( subject=Name(id='x', ctx=Load()), cases=[ match_case( pattern=MatchSequence( patterns=[ MatchValue( value=Constant(value=1)), MatchValue( value=Constant(value=2)), MatchStar(name='rest')]), body=[ Expr( value=Constant(value=Ellipsis))]), match_case( pattern=MatchSequence( patterns=[ MatchStar()]), body=[ Expr( value=Constant(value=Ellipsis))])])], type_ignores=[])
- class ast.MatchMapping(keys, patterns, rest)
匹配映射模式。
keys
是表达式节点的序列。patterns
是对应的模式节点序列。rest
是一个可选名称,可以指定它来捕获剩余的映射元素。 如匹配语句文档中所述,允许的键表达式受到限制。如果主题是一个映射,所有评估的键表达式都存在于映射中,并且与每个键对应的值与相应的子模式匹配,则此模式成功。 如果
rest
不是None
,如果整个映射模式成功,则包含剩余映射元素的 dict 将绑定到该名称。>>> print(ast.dump(ast.parse(""" ... match x: ... case {1: _, 2: _}: ... ... ... case {**rest}: ... ... ... """), indent=4)) Module( body=[ Match( subject=Name(id='x', ctx=Load()), cases=[ match_case( pattern=MatchMapping( keys=[ Constant(value=1), Constant(value=2)], patterns=[ MatchAs(), MatchAs()]), body=[ Expr( value=Constant(value=Ellipsis))]), match_case( pattern=MatchMapping(keys=[], patterns=[], rest='rest'), body=[ Expr( value=Constant(value=Ellipsis))])])], type_ignores=[])
- class ast.MatchClass(cls, patterns, kwd_attrs, kwd_patterns)
匹配类模式。
cls
是给出要匹配的名义类的表达式。patterns
是要与类定义的模式匹配属性序列匹配的模式节点序列。kwd_attrs
是要匹配的附加属性序列(在类模式中指定为关键字参数),kwd_patterns
是相应的模式(在类模式中指定为关键字值)。如果主题是指定类的实例,所有位置模式都匹配相应的类定义属性,并且任何指定的关键字属性与其相应的模式匹配,则此模式成功。
注意:类可以定义一个返回 self 的属性,以便将模式节点与正在匹配的实例进行匹配。 一些内置类型也以这种方式匹配,如 match 语句文档中所述。
>>> print(ast.dump(ast.parse(""" ... match x: ... case Point2D(0, 0): ... ... ... case Point3D(x=0, y=0, z=0): ... ... ... """), indent=4)) Module( body=[ Match( subject=Name(id='x', ctx=Load()), cases=[ match_case( pattern=MatchClass( cls=Name(id='Point2D', ctx=Load()), patterns=[ MatchValue( value=Constant(value=0)), MatchValue( value=Constant(value=0))], kwd_attrs=[], kwd_patterns=[]), body=[ Expr( value=Constant(value=Ellipsis))]), match_case( pattern=MatchClass( cls=Name(id='Point3D', ctx=Load()), patterns=[], kwd_attrs=[ 'x', 'y', 'z'], kwd_patterns=[ MatchValue( value=Constant(value=0)), MatchValue( value=Constant(value=0)), MatchValue( value=Constant(value=0))]), body=[ Expr( value=Constant(value=Ellipsis))])])], type_ignores=[])
- class ast.MatchAs(pattern, name)
匹配“as-pattern”、捕获模式或通配符模式。
pattern
包含主题将与之匹配的匹配模式。 如果模式是None
,则该节点代表一个捕获模式(即一个裸名)并且总是会成功。name
属性包含模式成功时将绑定的名称。 如果name
是None
,则pattern
也必须是None
并且节点表示通配符模式。>>> print(ast.dump(ast.parse(""" ... match x: ... case [x] as y: ... ... ... case _: ... ... ... """), indent=4)) Module( body=[ Match( subject=Name(id='x', ctx=Load()), cases=[ match_case( pattern=MatchAs( pattern=MatchSequence( patterns=[ MatchAs(name='x')]), name='y'), body=[ Expr( value=Constant(value=Ellipsis))]), match_case( pattern=MatchAs(), body=[ Expr( value=Constant(value=Ellipsis))])])], type_ignores=[])
- class ast.MatchOr(patterns)
匹配“或模式”。 or-模式依次将其每个子模式与主题匹配,直到成功为止。 然后认为 or 模式成功。 如果没有一个子模式成功,则 or 模式失败。
patterns
属性包含将与主题匹配的匹配模式节点列表。>>> print(ast.dump(ast.parse(""" ... match x: ... case [x] | (y): ... ... ... """), indent=4)) Module( body=[ Match( subject=Name(id='x', ctx=Load()), cases=[ match_case( pattern=MatchOr( patterns=[ MatchSequence( patterns=[ MatchAs(name='x')]), MatchAs(name='y')]), body=[ Expr( value=Constant(value=Ellipsis))])])], type_ignores=[])
函数和类定义
- class ast.FunctionDef(name, args, body, decorator_list, returns, type_comment)
一个函数定义。
name
是函数名的原始字符串。args
是一个 arguments 节点。body
是函数内部的节点列表。decorator_list
是要应用的装饰器列表,首先存储在最外层(即 列表中的第一个将最后应用)。returns
是返回注释。
- type_comment
type_comment
是一个可选字符串,带有类型注释作为注释。
- class ast.Lambda(args, body)
lambda
是可以在表达式中使用的最小函数定义。 与 FunctionDef 不同,body
持有单个节点。>>> print(ast.dump(ast.parse('lambda x,y: ...'), indent=4)) Module( body=[ Expr( value=Lambda( args=arguments( posonlyargs=[], args=[ arg(arg='x'), arg(arg='y')], kwonlyargs=[], kw_defaults=[], defaults=[]), body=Constant(value=Ellipsis)))], type_ignores=[])
- class ast.arguments(posonlyargs, args, vararg, kwonlyargs, kw_defaults, kwarg, defaults)
- 函数的参数。
- class ast.arg(arg, annotation, type_comment)
列表中的单个参数。
arg
是参数名的原始字符串,annotation
是它的注释,例如Str
或 Name 节点。- type_comment
type_comment
是可选字符串,类型注解作为注释
>>> print(ast.dump(ast.parse("""\ ... @decorator1 ... @decorator2 ... def f(a: 'annotation', b=1, c=2, *d, e, f=3, **g) -> 'return annotation': ... pass ... """), indent=4)) Module( body=[ FunctionDef( name='f', args=arguments( posonlyargs=[], args=[ arg( arg='a', annotation=Constant(value='annotation')), arg(arg='b'), arg(arg='c')], vararg=arg(arg='d'), kwonlyargs=[ arg(arg='e'), arg(arg='f')], kw_defaults=[ None, Constant(value=3)], kwarg=arg(arg='g'), defaults=[ Constant(value=1), Constant(value=2)]), body=[ Pass()], decorator_list=[ Name(id='decorator1', ctx=Load()), Name(id='decorator2', ctx=Load())], returns=Constant(value='return annotation'))], type_ignores=[])
- class ast.Return(value)
return
语句。>>> print(ast.dump(ast.parse('return 4'), indent=4)) Module( body=[ Return( value=Constant(value=4))], type_ignores=[])
- class ast.Yield(value)
class ast.YieldFrom(value) yield
或yield from
表达式。 因为这些是表达式,所以如果不使用发回的值,它们必须包含在 Expr 节点中。>>> print(ast.dump(ast.parse('yield x'), indent=4)) Module( body=[ Expr( value=Yield( value=Name(id='x', ctx=Load())))], type_ignores=[]) >>> print(ast.dump(ast.parse('yield from x'), indent=4)) Module( body=[ Expr( value=YieldFrom( value=Name(id='x', ctx=Load())))], type_ignores=[])
- class ast.Global(names)
class ast.Nonlocal(names) global
和nonlocal
语句。names
是原始字符串列表。>>> print(ast.dump(ast.parse('global x,y,z'), indent=4)) Module( body=[ Global( names=[ 'x', 'y', 'z'])], type_ignores=[]) >>> print(ast.dump(ast.parse('nonlocal x,y,z'), indent=4)) Module( body=[ Nonlocal( names=[ 'x', 'y', 'z'])], type_ignores=[])
- class ast.ClassDef(name, bases, keywords, starargs, kwargs, body, decorator_list)
一个类定义。
name
是类名的原始字符串bases
是显式指定基类的节点列表。starargs
和kwargs
都是一个节点,就像在函数调用中一样。 starargs 将被扩展以加入基类列表,kwargs 将被传递给元类。body
是代表类定义中代码的节点列表。decorator_list
是一个节点列表,如 FunctionDef。
>>> print(ast.dump(ast.parse("""\ ... @decorator1 ... @decorator2 ... class Foo(base1, base2, metaclass=meta): ... pass ... """), indent=4)) Module( body=[ ClassDef( name='Foo', bases=[ Name(id='base1', ctx=Load()), Name(id='base2', ctx=Load())], keywords=[ keyword( arg='metaclass', value=Name(id='meta', ctx=Load()))], body=[ Pass()], decorator_list=[ Name(id='decorator1', ctx=Load()), Name(id='decorator2', ctx=Load())])], type_ignores=[])
异步和等待
- class ast.AsyncFunctionDef(name, args, body, decorator_list, returns, type_comment)
async def
函数定义。 具有与 FunctionDef 相同的字段。
- class ast.Await(value)
await
表达式。value
就是它所等待的。 仅在 AsyncFunctionDef 的主体中有效。
>>> print(ast.dump(ast.parse("""\
... async def f():
... await other_func()
... """), indent=4))
Module(
body=[
AsyncFunctionDef(
name='f',
args=arguments(
posonlyargs=[],
args=[],
kwonlyargs=[],
kw_defaults=[],
defaults=[]),
body=[
Expr(
value=Await(
value=Call(
func=Name(id='other_func', ctx=Load()),
args=[],
keywords=[])))],
decorator_list=[])],
type_ignores=[])
- class ast.AsyncFor(target, iter, body, orelse, type_comment)
class ast.AsyncWith(items, body, type_comment)
async for
循环和async with
上下文管理器。 它们分别与 For 和 With 具有相同的字段。 仅在 AsyncFunctionDef 的主体中有效。
笔记
ast.parse()解析字符串时,算子节点(ast.operator
、ast.unaryop
、ast.cmpop
、ast.boolop
的子类)和 ast.expr_context
) 在返回的树上将是单例。 对一个的更改将反映在所有其他出现的相同值中(例如 ast.Add)。
ast 助手
除了节点类之外,ast 模块定义了这些用于遍历抽象语法树的实用函数和类:
- ast.parse(source, filename='<unknown>', mode='exec', *, type_comments=False, feature_version=None)
将源解析为 AST 节点。 相当于
compile(source, filename, mode, ast.PyCF_ONLY_AST)
。如果给出
type_comments=True
,则修改解析器以检查和返回 PEP 484 和 PEP 526[ X146X]。 这相当于将 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]
。如果源包含空字符 ('0'),则引发 ValueError。
警告
请注意,将源代码成功解析为 AST 对象并不能保证所提供的源代码是可以执行的有效 Python 代码,因为编译步骤可能会引发进一步的 SyntaxError 异常。 例如,源
return 42
为 return 语句生成一个有效的 AST 节点,但它不能单独编译(它需要在函数节点内)。特别是, ast.parse() 不会做任何范围检查,编译步骤会这样做。
警告
由于 Python 的 AST 编译器中的堆栈深度限制,有可能使用足够大/复杂的字符串使 Python 解释器崩溃。
3.8 版更改: 添加
type_comments
、mode='func_type'
和feature_version
。
- ast.unparse(ast_obj)
解解析 ast.AST 对象并生成一个字符串,其中的代码将生成等效的 ast.AST 对象,如果用 ast.parse() 解析回来。
警告
生成的代码字符串不一定等于生成 ast.AST 对象的原始代码(没有任何编译器优化,例如常量元组/冻结集)。
警告
试图解析一个高度复杂的表达式会导致 RecursionError。
3.9 版中的新功能。
- ast.literal_eval(node_or_string)
安全地计算包含 Python 文字或容器显示的表达式节点或字符串。 提供的字符串或节点只能包含以下 Python 文字结构:字符串、字节、数字、元组、列表、字典、集合、布尔值、
None
和Ellipsis
。这可用于安全地评估包含来自不受信任来源的 Python 值的字符串,而无需自己解析这些值。 它不能评估任意复杂的表达式,例如涉及运算符或索引。
警告
由于 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 为真,则使用 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
属性。 填充生成的节点相当繁琐,因此该助手通过将这些属性设置为父节点的值,在尚未设置的地方递归添加这些属性。 它从 节点 开始递归地工作。
- 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._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 将遍历 AST 并使用访问者方法的返回值来替换或删除旧节点。 如果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)
返回 节点 中树的格式化转储。 这主要用于调试目的。 如果 annotate_fields 为真(默认情况下),返回的字符串将显示字段的名称和值。 如果 annotate_fields 为 false,则通过省略明确的字段名称,结果字符串将更加紧凑。 默认情况下不会转储行号和列偏移等属性。 如果需要,可以将 include_attributes 设置为 true。
如果 indent 是非负整数或字符串,则树将使用该缩进级别进行漂亮打印。 缩进级别 0、负数或
""
只会插入换行符。None
(默认)选择单线表示。 使用正整数缩进每级缩进多少个空格。 如果 indent 是一个字符串(例如"\t"
),则该字符串用于缩进每个级别。3.9 版更改: 添加 缩进 选项。
编译器标志
以下标志可以传递给 compile() 以更改对程序编译的影响:
- ast.PyCF_ALLOW_TOP_LEVEL_AWAIT
启用对顶级
await
、async for
、async with
和异步理解的支持。3.8 版中的新功能。
- ast.PyCF_ONLY_AST
- 生成并返回抽象语法树,而不是返回已编译的代码对象。
- ast.PyCF_TYPE_COMMENTS
启用对 PEP 484 和 PEP 526 样式类型注释的支持 (
# type: <type>
,# type: ignore <stuff>
.3.8 版中的新功能。
命令行使用
3.9 版中的新功能。
ast 模块可以从命令行作为脚本执行。 它很简单:
python -m ast [-m <mode>] [-a] [infile]
接受以下选项:
- -h, --help
- 显示帮助信息并退出。
- -m <mode>
--mode <mode>
- 指定必须编译的代码类型,例如 parse() 中的 mode 参数。
- --no-type-comments
- 不要解析类型注释。
- -a, --include-attributes
- 包括行号和列偏移等属性。
- -i <indent>
--indent <indent>
- AST 中节点的缩进(空格数)。
如果指定了 infile
,其内容将被解析为 AST 并转储到标准输出。 否则,从标准输入读取内容。
也可以看看
Green Tree Snakes 是一个外部文档资源,其中包含有关使用 Python AST 的详细信息。
ASTTokens 使用生成它们的源代码中的标记和文本的位置来注释 Python AST。 这对于进行源代码转换的工具很有帮助。
leoAst.py 通过在令牌和 ast 节点之间插入双向链接,统一了 Python 程序的基于令牌和基于解析树的视图。
LibCST 将代码解析为一个具体的语法树,它看起来像一个 ast 树并保留所有格式细节。 它对于构建自动重构 (codemod) 应用程序和 linter 很有用。
Parso 是一个 Python 解析器,支持不同 Python 版本(在多个 Python 版本中)的错误恢复和往返解析。 Parso 还能够在您的 python 文件中列出多个语法错误。