ast
---抽象语法树¶
源代码: Lib/ast.py
这个 ast
模块帮助python应用程序处理python抽象语法语法树。抽象语法本身可能会随着每个Python版本的变化而变化;这个模块有助于以编程方式找出当前语法的外观。
通过传递可以生成抽象语法树 ast.PyCF_ONLY_AST
作为标志 compile()
内置函数,或使用 parse()
此模块中提供的帮助程序。结果将是所有类都继承自的对象树 ast.AST
. 抽象语法树可以使用内置的 compile()
功能。
抽象语法¶
抽象语法目前定义如下:
-- 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)
| 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)
withitem = (expr context_expr, expr? optional_vars)
type_ignore = TypeIgnore(int lineno, string tag)
}
节点类¶
- class ast.AST¶
这是所有AST节点类的基础。实际的节点类是从
Parser/Python.asdl
复制的文件 below . 它们在_ast
C模块并在中重新导出ast
.抽象语法中为每个左侧符号定义了一个类(例如,
ast.stmt
或ast.expr
)。此外,在右侧为每个构造函数定义了一个类;这些类继承自左侧树的类。例如,ast.BinOp
继承自ast.expr
. 对于具有备选方案的生产规则(也称为“sums”),左侧类是抽象的:只创建特定构造函数节点的实例。- _fields¶
每个具体类都有一个属性
_fields
它给出了所有子节点的名称。具体类的每个实例对于每个子节点都有一个属性,属于语法中定义的类型。例如,
ast.BinOp
实例具有属性left
类型的ast.expr
.如果在语法中将这些属性标记为可选(使用问号),则该值可能是
None
. 如果属性可以有零个或多个值(用星号标记),则这些值表示为python列表。使用以下命令编译ast时,所有可能的属性都必须存在并具有有效值compile()
.
- 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)¶
恒定值。这个
value
的属性Constant
literal包含它所表示的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
列表,带有None
在中的相应位置keys
.>>> 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)¶
A
*var
变量引用。value
保存变量,通常是Name
节点。在生成Call
节点*args
.>>> 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
,AName
,ALambda
,AYield
或YieldFrom
节点。>>> print(ast.dump(ast.parse('-a'), indent=4)) Module( body=[ Expr( value=UnaryOp( op=USub(), operand=Name(id='a', ctx=Load())))], type_ignores=[])
- class ast.UnaryOp(op, operand)¶
一元手术。
op
是接线员,而且operand
任何表达式节点。
- class ast.UAdd¶
- class ast.USub¶
- class ast.Not¶
- class ast.Invert¶
一元运算符标记。
Not
是not
关键字,Invert
是~
操作员。>>> print(ast.dump(ast.parse('not x', mode='eval'), indent=4)) Expression( body=UnaryOp( op=Not(), operand=Name(id='x', ctx=Load())))
- class ast.BinOp(left, op, right)¶
二进制运算(如加法或除法)。
op
是接线员,而且left
和right
是任何表达式节点。>>> print(ast.dump(ast.parse('x + y', mode='eval'), indent=4)) Expression( body=BinOp( left=Name(id='x', ctx=Load()), op=Add(), right=Name(id='y', ctx=Load())))
- class ast.Add¶
- class ast.Sub¶
- class ast.Mult¶
- class ast.Div¶
- class ast.FloorDiv¶
- class ast.Mod¶
- class ast.Pow¶
- class ast.LShift¶
- class ast.RShift¶
- class ast.BitOr¶
- class ast.BitXor¶
- class ast.BitAnd¶
- class ast.MatMult¶
二进制运算符标记。
- class ast.BoolOp(op, values)¶
布尔运算“或”或“和”。
op
是Or
或And
.values
是否涉及价值观。具有相同运算符的连续操作,例如a or b or c
,将折叠为具有多个值的一个节点。这不包括
not
,这是一个UnaryOp
.>>> print(ast.dump(ast.parse('x or y', mode='eval'), indent=4)) Expression( body=BoolOp( op=Or(), values=[ Name(id='x', ctx=Load()), Name(id='y', ctx=Load())]))
- class ast.Compare(left, ops, comparators)¶
两个或多个值的比较。
left
是比较中的第一个值,ops
操作员列表,以及comparators
比较中第一个元素之后的值列表。>>> print(ast.dump(ast.parse('1 <= a < 10', mode='eval'), indent=4)) Expression( body=Compare( left=Constant(value=1), ops=[ LtE(), Lt()], comparators=[ Name(id='a', ctx=Load()), Constant(value=10)]))
- class ast.Eq¶
- class ast.NotEq¶
- class ast.Lt¶
- class ast.LtE¶
- class ast.Gt¶
- class ast.GtE¶
- class ast.Is¶
- class ast.IsNot¶
- class ast.In¶
- class ast.NotIn¶
比较运算符标记。
- class ast.Call(func, args, keywords, 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
是索引、切片或键。它可以是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
,直接或作为Tuple
.>>> print(ast.dump(ast.parse('l[1:2]', mode='eval'), indent=4)) Expression( body=Subscript( value=Name(id='l', ctx=Load()), slice=Slice( lower=Constant(value=1), upper=Constant(value=2)), ctx=Load()))
理解¶
- class ast.ListComp(elt, generators)¶
- class ast.SetComp(elt, generators)¶
- class ast.GeneratorExp(elt, generators)¶
- class ast.DictComp(key, value, generators)¶
列出并设置理解、生成器表达式和字典理解。
elt
(或)key
和value
)是表示将为每个项计算的部分的单个节点。generators
是一个列表comprehension
节点。>>> print(ast.dump(ast.parse('[x for x in numbers]', mode='eval'), indent=4)) Expression( body=ListComp( elt=Name(id='x', ctx=Load()), generators=[ comprehension( target=Name(id='x', ctx=Store()), iter=Name(id='numbers', ctx=Load()), ifs=[], is_async=0)])) >>> print(ast.dump(ast.parse('{x: x**2 for x in numbers}', mode='eval'), indent=4)) Expression( body=DictComp( key=Name(id='x', ctx=Load()), value=BinOp( left=Name(id='x', ctx=Load()), op=Pow(), right=Constant(value=2)), generators=[ comprehension( target=Name(id='x', ctx=Store()), iter=Name(id='numbers', ctx=Load()), ifs=[], is_async=0)])) >>> print(ast.dump(ast.parse('{x for x in numbers}', mode='eval'), indent=4)) Expression( body=SetComp( elt=Name(id='x', ctx=Load()), generators=[ comprehension( target=Name(id='x', ctx=Store()), iter=Name(id='numbers', ctx=Load()), ifs=[], is_async=0)]))
- class ast.comprehension(target, iter, ifs, is_async)¶
一
for
理解中的从句。target
是用于每个元素的引用-通常是Name
或Tuple
节点。iter
是要迭代的对象。ifs
是测试表达式的列表:每个for
子句可以有多个ifs
.is_async
表示理解是异步的(使用async for
而不是for
). 该值是一个整数(0或1)。>>> print(ast.dump(ast.parse('[ord(c) for line in file for c in line]', mode='eval'), ... indent=4)) # Multiple comprehensions in one. Expression( body=ListComp( elt=Call( func=Name(id='ord', ctx=Load()), args=[ Name(id='c', ctx=Load())], keywords=[]), generators=[ comprehension( target=Name(id='line', ctx=Store()), iter=Name(id='file', ctx=Load()), ifs=[], is_async=0), comprehension( target=Name(id='c', ctx=Store()), iter=Name(id='line', ctx=Load()), ifs=[], is_async=0)])) >>> print(ast.dump(ast.parse('(n**2 for n in it if n>5 if n<10)', mode='eval'), ... indent=4)) # generator comprehension Expression( body=GeneratorExp( elt=BinOp( left=Name(id='n', ctx=Load()), op=Pow(), right=Constant(value=2)), generators=[ comprehension( target=Name(id='n', ctx=Store()), iter=Name(id='it', ctx=Load()), ifs=[ Compare( left=Name(id='n', ctx=Load()), ops=[ Gt()], comparators=[ Constant(value=5)]), Compare( left=Name(id='n', ctx=Load()), ops=[ Lt()], comparators=[ Constant(value=10)])], is_async=0)])) >>> print(ast.dump(ast.parse('[i async for i in soc]', mode='eval'), ... indent=4)) # Async comprehension Expression( body=ListComp( elt=Name(id='i', ctx=Load()), generators=[ comprehension( target=Name(id='i', ctx=Store()), iter=Name(id='soc', ctx=Load()), ifs=[], is_async=1)]))
声明¶
- class ast.Assign(targets, value, type_comment)¶
任务。
targets
是一个节点列表,并且value
是单个节点。中的多个节点
targets
表示为每个分配相同的值。解包是通过放置Tuple
或List
在内部targets
.- type_comment¶
type_comment
是一个可选字符串,类型批注作为注释。
>>> print(ast.dump(ast.parse('a = b = 1'), indent=4)) # Multiple assignment Module( body=[ Assign( targets=[ Name(id='a', ctx=Store()), Name(id='b', ctx=Store())], value=Constant(value=1))], type_ignores=[]) >>> print(ast.dump(ast.parse('a,b = c'), indent=4)) # Unpacking Module( body=[ Assign( targets=[ Tuple( elts=[ Name(id='a', ctx=Store()), Name(id='b', ctx=Store())], ctx=Store())], value=Name(id='c', ctx=Load()))], type_ignores=[])
- class ast.AnnAssign(target, annotation, value, simple)¶
带有类型注释的赋值。
target
是单个节点,可以是Name
,AAttribute
或ASubscript
.annotation
是注释,例如Constant
或Name
节点。value
是单个可选节点。simple
对于Name
节点target
不出现在括号之间,因此是纯名称而不是表达式。>>> 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
是一个Name
节点x
(与Store
上下文),op
是Add
和value
是一个Constant
值为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)¶
A
raise
语句。exc
是要引发的异常对象,通常是Call
或Name
或None
对于独立的raise
.cause
是y
在里面raise x from 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¶
A
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
是“from”名称的原始字符串,没有任何前导点,或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
子句在as t中没有特殊的表示,而是作为额外的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
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)¶
A
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
是用于保存异常的名称的原始字符串,或None
如果条款没有as foo
.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)¶
A
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.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)¶
A
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)¶
A
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 . 这相当于添加ast.PyCF_TYPE_COMMENTS
传递给compile()
. 这将报告错误放置的类型注释的语法错误。如果没有此标志,类型注释将被忽略,并且type_comment
所选AST节点上的字段将始终为None
. 此外,在# type: ignore
注释将作为type_ignores
属性Module
(否则,它总是一个空列表)。此外,如果
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]
.警告
由于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
如果没有docstring。如果 清洁的 是真的,用inspect.cleandoc()
.在 3.5 版更改:
AsyncFunctionDef
现在支持。
- ast.get_source_segment(source, node, *, padded=False)¶
获取的源代码段 source 产生的 node . 如果一些位置信息 (
lineno
,end_lineno
,col_offset
或end_col_offset
)丢失,返回None
.如果 衬垫 是
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)¶
生成一个元组
(fieldname, value)
中的每个字段node._fields
现在在 node .
- ast.iter_child_nodes(node)¶
生成的所有直接子节点 node 也就是说,作为节点的所有字段和作为节点列表的所有字段项。
- ast.walk(node)¶
以递归方式生成树中从开始的所有子节点 node (包括 node 它本身),没有指定的顺序。如果您只想在适当的位置修改节点,而不关心上下文,那么这很有用。
- class ast.NodeVisitor¶
一个节点访问者基类,它遍历抽象语法树并为找到的每个节点调用访问者函数。此函数可以返回一个值,该值由
visit()
方法。这个类应该是子类的,子类添加了访问者方法。
- visit(node)¶
访问节点。默认实现调用调用的方法
self.visit_{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¶
A
NodeVisitor
遍历抽象语法树并允许修改节点的子类。这个
NodeTransformer
将遍历ast并使用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。
如果 缩进 是一个非负整数或字符串,则树将以该缩进级别漂亮地打印出来。缩进级别为0、负或
""
只插入换行符。None
(默认设置)选择单线表示。使用正整数缩进可使每个级别缩进多个空格。如果 缩进 是字符串(例如"\t"
,该字符串用于缩进每个级别。在 3.9 版更改: 增加了 缩进 选择权。
编译器标志¶
可以将以下标志传递给 compile()
要更改对程序编译的影响,请执行以下操作:
- ast.PyCF_ALLOW_TOP_LEVEL_AWAIT¶
启用对顶层的支持
await
,async for
,async with
和异步理解。3.8 新版功能.
- ast.PyCF_ONLY_AST¶
生成并返回抽象语法树,而不是返回已编译的代码对象。
命令行用法¶
3.9 新版功能.
这个 ast
模块可以作为脚本从命令行执行。它简单如下:
python -m ast [-m <mode>] [-a] [infile]
接受以下选项:
- -h, --help¶
显示帮助消息并退出。
- --no-type-comments¶
不要分析类型注释。
- -a, --include-attributes¶
包括行号和列偏移等属性。
如果 infile
它的内容被解析为AST并转储到stdout。否则,将从stdin读取内容。
参见
Green Tree Snakes <https://greentreesnakes.readthedocs.io/> _作为一个外部文档资源,它对使用Python AST有很好的细节。
ASTTokens 用生成标记的源代码中的标记和文本的位置来注释pythonast。这对于进行源代码转换的工具非常有用。
leoAst.py 通过在令牌和ast节点之间插入双向链接,统一了python程序的基于令牌和基于解析树的视图。
LibCST 将代码解析为一个具体的语法树,该树看起来像ast树,并保留所有格式详细信息。它对于构建自动重构(codemod)应用程序和linter非常有用。
Parso 是一个Python解析器,支持不同Python版本(在多个Python版本中)的错误恢复和往返解析。Parso还可以在python文件中列出多个语法错误。