ast
— 抽象語法樹¶
原始碼: Lib/ast.py
ast
模組幫助 Python 應用程式處理 Python 抽象語法樹。 抽象語法本身可能會隨著每個 Python 版本的釋出而更改;此模組有助於以程式設計方式找出當前語法的樣子。
抽象語法樹可以透過將 ast.PyCF_ONLY_AST
作為標誌傳遞給 compile()
內建函式,或者使用此模組中提供的 parse()
助手來生成。 結果將是一個物件樹,其類都繼承自 ast.AST
。 可以使用內建的 compile()
函式將抽象語法樹編譯為 Python 程式碼物件。
抽象語法¶
抽象語法目前定義如下
-- ASDL's 4 builtin types are:
-- identifier, int, string, constant
module Python
{
mod = Module(stmt* body, type_ignore* type_ignores)
| Interactive(stmt* body)
| Expression(expr body)
| FunctionType(expr* argtypes, expr returns)
stmt = FunctionDef(identifier name, arguments args,
stmt* body, expr* decorator_list, expr? returns,
string? type_comment, type_param* type_params)
| AsyncFunctionDef(identifier name, arguments args,
stmt* body, expr* decorator_list, expr? returns,
string? type_comment, type_param* type_params)
| ClassDef(identifier name,
expr* bases,
keyword* keywords,
stmt* body,
expr* decorator_list,
type_param* type_params)
| Return(expr? value)
| Delete(expr* targets)
| Assign(expr* targets, expr value, string? type_comment)
| TypeAlias(expr name, type_param* type_params, expr value)
| AugAssign(expr target, operator op, expr value)
-- 'simple' indicates that we annotate simple name without parens
| AnnAssign(expr target, expr annotation, expr? value, int simple)
-- use 'orelse' because else is a keyword in target languages
| For(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment)
| AsyncFor(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment)
| While(expr test, stmt* body, stmt* orelse)
| If(expr test, stmt* body, stmt* orelse)
| With(withitem* items, stmt* body, string? type_comment)
| AsyncWith(withitem* items, stmt* body, string? type_comment)
| Match(expr subject, match_case* cases)
| Raise(expr? exc, expr? cause)
| Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)
| TryStar(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)
| Assert(expr test, expr? msg)
| Import(alias* names)
| ImportFrom(identifier? module, alias* names, int? level)
| Global(identifier* names)
| Nonlocal(identifier* names)
| Expr(expr value)
| Pass | Break | Continue
-- col_offset is the byte offset in the utf8 string the parser uses
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
-- BoolOp() can use left & right?
expr = BoolOp(boolop op, expr* values)
| NamedExpr(expr target, expr value)
| BinOp(expr left, operator op, expr right)
| UnaryOp(unaryop op, expr operand)
| Lambda(arguments args, expr body)
| IfExp(expr test, expr body, expr orelse)
| Dict(expr* keys, expr* values)
| Set(expr* elts)
| ListComp(expr elt, comprehension* generators)
| SetComp(expr elt, comprehension* generators)
| DictComp(expr key, expr value, comprehension* generators)
| GeneratorExp(expr elt, comprehension* generators)
-- the grammar constrains where yield expressions can occur
| Await(expr value)
| Yield(expr? value)
| YieldFrom(expr value)
-- need sequences for compare to distinguish between
-- x < 4 < 3 and (x < 4) < 3
| Compare(expr left, cmpop* ops, expr* comparators)
| Call(expr func, expr* args, keyword* keywords)
| FormattedValue(expr value, int conversion, expr? format_spec)
| JoinedStr(expr* values)
| Constant(constant value, string? kind)
-- the following expression can appear in assignment context
| Attribute(expr value, identifier attr, expr_context ctx)
| Subscript(expr value, expr slice, expr_context ctx)
| Starred(expr value, expr_context ctx)
| Name(identifier id, expr_context ctx)
| List(expr* elts, expr_context ctx)
| Tuple(expr* elts, expr_context ctx)
-- can appear only in Subscript
| Slice(expr? lower, expr? upper, expr? step)
-- col_offset is the byte offset in the utf8 string the parser uses
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
expr_context = Load | Store | Del
boolop = And | Or
operator = Add | Sub | Mult | MatMult | Div | Mod | Pow | LShift
| RShift | BitOr | BitXor | BitAnd | FloorDiv
unaryop = Invert | Not | UAdd | USub
cmpop = Eq | NotEq | Lt | LtE | Gt | GtE | Is | IsNot | In | NotIn
comprehension = (expr target, expr iter, expr* ifs, int is_async)
excepthandler = ExceptHandler(expr? type, identifier? name, stmt* body)
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
arguments = (arg* posonlyargs, arg* args, arg? vararg, arg* kwonlyargs,
expr* kw_defaults, arg? kwarg, expr* defaults)
arg = (identifier arg, expr? annotation, string? type_comment)
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
-- keyword arguments supplied to call (NULL identifier for **kwargs)
keyword = (identifier? arg, expr value)
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
-- import name with optional 'as' alias.
alias = (identifier name, identifier? asname)
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
withitem = (expr context_expr, expr? optional_vars)
match_case = (pattern pattern, expr? guard, stmt* body)
pattern = MatchValue(expr value)
| MatchSingleton(constant value)
| MatchSequence(pattern* patterns)
| MatchMapping(expr* keys, pattern* patterns, identifier? rest)
| MatchClass(expr cls, pattern* patterns, identifier* kwd_attrs, pattern* kwd_patterns)
| MatchStar(identifier? name)
-- The optional "rest" MatchMapping parameter handles capturing extra mapping keys
| MatchAs(pattern? pattern, identifier? name)
| MatchOr(pattern* patterns)
attributes (int lineno, int col_offset, int end_lineno, int end_col_offset)
type_ignore = TypeIgnore(int lineno, string tag)
type_param = TypeVar(identifier name, expr? bound, expr? default_value)
| ParamSpec(identifier name, expr? default_value)
| TypeVarTuple(identifier name, expr? default_value)
attributes (int lineno, int col_offset, int end_lineno, int end_col_offset)
}
節點類¶
- class ast.AST¶
這是所有 AST 節點類的基礎。 實際的節點類派生自
Parser/Python.asdl
檔案,該檔案在上方重新生成。 它們在_ast
C 模組中定義,並在ast
中重新匯出。抽象語法中為每個左側符號定義一個類(例如,
ast.stmt
或ast.expr
)。 此外,為右側的每個建構函式定義一個類;這些類繼承自左側樹的類。 例如,ast.BinOp
繼承自ast.expr
。 對於具有備選方案(又名“和”)的生成規則,左側類是抽象的:僅建立特定建構函式節點的例項。- _fields¶
每個具體類都有一個屬性
_fields
,它給出所有子節點的名稱。具體類的每個例項都有一個屬性,用於每個子節點,其型別在語法中定義。 例如,
ast.BinOp
例項具有一個型別為ast.expr
的屬性left
。如果這些屬性在語法中標記為可選(使用問號),則該值可能為
None
。 如果屬性可以具有零個或多個值(用星號標記),則這些值表示為 Python 列表。 使用compile()
編譯 AST 時,所有可能的屬性都必須存在並具有有效值。
- _field_types¶
每個具體類上的
_field_types
屬性是一個字典,它將欄位名稱(也列在_fields
中)對映到它們的型別。>>> ast.TypeVar._field_types {'name': <class 'str'>, 'bound': ast.expr | None, 'default_value': ast.expr | None}
3.13 版本新增。
- lineno¶
- col_offset¶
- end_lineno¶
- end_col_offset¶
ast.expr
和ast.stmt
子類的例項具有lineno
、col_offset
、end_lineno
和end_col_offset
屬性。lineno
和end_lineno
是源文字跨度的第一個和最後一個行號(從 1 開始索引,因此第一行是行 1),而col_offset
和end_col_offset
是生成節點的第一個和最後一個標記的相應 UTF-8 位元組偏移量。 記錄 UTF-8 偏移量是因為解析器在內部使用 UTF-8。請注意,編譯器不需要結束位置,因此是可選的。 結束偏移量在最後一個符號之後,例如,可以使用
source_line[node.col_offset : node.end_col_offset]
獲取單行表示式節點的源片段。
類
ast.T
的建構函式按如下方式解析其引數如果有位置引數,則必須與
T._fields
中的項一樣多; 它們將被分配為這些名稱的屬性。如果有關鍵字引數,它們會將同名屬性設定為給定值。
例如,要建立和填充
ast.UnaryOp
節點,可以使用node = ast.UnaryOp(ast.USub(), ast.Constant(5, lineno=0, col_offset=0), lineno=0, col_offset=0)
如果語法中可選的欄位在建構函式中被省略,它將預設為
None
。如果省略列表欄位,則預設為空列表。如果省略型別為ast.expr_context
的欄位,它將預設為Load()
。如果省略任何其他欄位,則會引發DeprecationWarning
,並且 AST 節點將不包含此欄位。在 Python 3.15 中,此條件將引發錯誤。
在 3.8 版本中更改: 類 ast.Constant
現在用於所有常量。
在 3.9 版本中更改: 簡單索引用它們的值表示,擴充套件切片用元組表示。
自 3.8 版本起已棄用: 舊類 ast.Num
、ast.Str
、ast.Bytes
、ast.NameConstant
和 ast.Ellipsis
仍然可用,但它們將在未來的 Python 版本中被刪除。在此期間,例項化它們將返回不同類的例項。
自 3.9 版本起已棄用: 舊類 ast.Index
和 ast.ExtSlice
仍然可用,但它們將在未來的 Python 版本中被刪除。在此期間,例項化它們將返回不同類的例項。
自 3.13 版本起已棄用,將在 3.15 版本中刪除: 之前的 Python 版本允許建立缺少必需欄位的 AST 節點。同樣,AST 節點建構函式允許將任意關鍵字引數設定為 AST 節點的屬性,即使它們與 AST 節點的任何欄位都不匹配。此行為已被棄用,並將在 Python 3.15 中刪除。
注意
此處顯示的特定節點類的描述最初改編自出色的 Green Tree Snakes 專案及其所有貢獻者。
根節點¶
- class ast.Module(body, type_ignores)¶
一個 Python 模組,與 檔案輸入 相同。由預設
"exec"
*模式* 中的ast.parse()
生成的節點型別。type_ignores
是模組的型別忽略註釋的list
;有關更多詳細資訊,請參閱ast.parse()
。>>> print(ast.dump(ast.parse('x = 1'), indent=4)) Module( body=[ Assign( targets=[ Name(id='x', ctx=Store())], value=Constant(value=1))])
- class ast.Expression(body)¶
一個單獨的 Python 表示式輸入。當 *mode* 為
"eval"
時,由ast.parse()
生成的節點型別。body
是一個單獨的節點,屬於表示式型別之一。>>> print(ast.dump(ast.parse('123', mode='eval'), indent=4)) Expression( body=Constant(value=123))
- class ast.Interactive(body)¶
一個單獨的 互動式輸入,如 互動模式 中所示。當 *mode* 為
"single"
時,由ast.parse()
生成的節點型別。>>> print(ast.dump(ast.parse('x = 1; y = 2', mode='single'), indent=4)) Interactive( body=[ Assign( targets=[ Name(id='x', ctx=Store())], value=Constant(value=1)), Assign( targets=[ Name(id='y', ctx=Store())], value=Constant(value=2))])
- class ast.FunctionType(argtypes, returns)¶
舊式函式型別註釋的表示形式,因為 3.5 之前的 Python 版本不支援 PEP 484 註釋。當 *mode* 為
"func_type"
時,由ast.parse()
生成的節點型別。此類型別註釋如下所示
def sum_two_number(a, b): # type: (int, int) -> int return a + b
returns
是單個 表示式節點。>>> print(ast.dump(ast.parse('(int, str) -> List[int]', mode='func_type'), indent=4)) FunctionType( argtypes=[ Name(id='int', ctx=Load()), Name(id='str', ctx=Load())], returns=Subscript( value=Name(id='List', ctx=Load()), slice=Name(id='int', ctx=Load()), ctx=Load()))
在 3.8 版本中新增。
字面量¶
- class ast.Constant(value)¶
一個常量值。
Constant
字面量的value
屬性包含它所表示的 Python 物件。表示的值可以是簡單型別,例如數字、字串或None
,但如果它們的所有元素都是常量,則也可以是不可變的容器型別(元組和凍結集合)。>>> 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())]), conversion=-1, format_spec=JoinedStr( values=[ Constant(value='.3')]))]))
- class ast.List(elts, ctx)¶
- class ast.Tuple(elts, ctx)¶
一個列表或元組。
elts
儲存表示元素的節點列表。ctx
如果容器是賦值目標(即(x,y)=something
),則為Store
,否則為Load
。>>> print(ast.dump(ast.parse('[1, 2, 3]', mode='eval'), indent=4)) Expression( body=List( elts=[ Constant(value=1), Constant(value=2), Constant(value=3)], ctx=Load())) >>> print(ast.dump(ast.parse('(1, 2, 3)', mode='eval'), indent=4)) Expression( body=Tuple( elts=[ Constant(value=1), Constant(value=2), Constant(value=3)], ctx=Load()))
- class ast.Set(elts)¶
一個集合。
elts
儲存表示集合元素的節點列表。>>> print(ast.dump(ast.parse('{1, 2, 3}', mode='eval'), indent=4)) Expression( body=Set( elts=[ Constant(value=1), Constant(value=2), Constant(value=3)]))
- class ast.Dict(keys, values)¶
一個字典。
keys
和values
分別儲存代表鍵和值的節點列表,順序匹配(呼叫dictionary.keys()
和dictionary.values()
時返回的結果)。當使用字典字面量進行字典解包時,要展開的表示式會放在
values
列表中,而keys
中相應位置的值為None
。>>> print(ast.dump(ast.parse('{"a":1, **d}', mode='eval'), indent=4)) Expression( body=Dict( keys=[ Constant(value='a'), None], values=[ Constant(value=1), Name(id='d', ctx=Load())]))
變數¶
- class ast.Name(id, ctx)¶
一個變數名。
id
以字串形式儲存變數名,而ctx
是以下型別之一。
- class ast.Load¶
- class ast.Store¶
- class ast.Del¶
變數引用可以用於載入變數的值、為變數賦予新值或刪除變數。變數引用被賦予一個上下文,以區分這些情況。
>>> print(ast.dump(ast.parse('a'), indent=4)) Module( body=[ Expr( value=Name(id='a', ctx=Load()))]) >>> print(ast.dump(ast.parse('a = 1'), indent=4)) Module( body=[ Assign( targets=[ Name(id='a', ctx=Store())], value=Constant(value=1))]) >>> print(ast.dump(ast.parse('del a'), indent=4)) Module( body=[ Delete( targets=[ Name(id='a', ctx=Del())])])
- class ast.Starred(value, ctx)¶
一個
*var
變數引用。value
儲存該變數,通常是一個Name
節點。當構建帶有*args
的Call
節點時,必須使用此型別。>>> print(ast.dump(ast.parse('a, *b = it'), indent=4)) Module( body=[ Assign( targets=[ Tuple( elts=[ Name(id='a', ctx=Store()), Starred( value=Name(id='b', ctx=Store()), ctx=Store())], ctx=Store())], value=Name(id='it', ctx=Load()))])
表示式¶
- class ast.Expr(value)¶
當一個表示式(如函式呼叫)作為語句本身出現,其返回值未被使用或儲存時,它會被包裝在這個容器中。
value
儲存本節中的其他節點之一,一個Constant
、一個Name
、一個Lambda
、一個Yield
或一個YieldFrom
節點。>>> print(ast.dump(ast.parse('-a'), indent=4)) Module( body=[ Expr( value=UnaryOp( op=USub(), operand=Name(id='a', ctx=Load())))])
- class ast.UnaryOp(op, operand)¶
一個一元運算。
op
是運算子,而operand
是任何表示式節點。
- class ast.UAdd¶
- class ast.USub¶
- class ast.Not¶
- class ast.Invert¶
一元運算子標記。
Not
是not
關鍵字,Invert
是~
運算子。>>> print(ast.dump(ast.parse('not x', mode='eval'), indent=4)) Expression( body=UnaryOp( op=Not(), operand=Name(id='x', ctx=Load())))
- class ast.BinOp(left, op, right)¶
一個二元運算(如加法或除法)。
op
是運算子,而left
和right
是任何表示式節點。>>> print(ast.dump(ast.parse('x + y', mode='eval'), indent=4)) Expression( body=BinOp( left=Name(id='x', ctx=Load()), op=Add(), right=Name(id='y', ctx=Load())))
- class ast.Add¶
- class ast.Sub¶
- class ast.Mult¶
- class ast.Div¶
- class ast.FloorDiv¶
- class ast.Mod¶
- class ast.Pow¶
- class ast.LShift¶
- class ast.RShift¶
- class ast.BitOr¶
- class ast.BitXor¶
- class ast.BitAnd¶
- class ast.MatMult¶
二元運算子標記。
- class ast.BoolOp(op, values)¶
一個布林運算,‘or’ 或 ‘and’。
op
是Or
或And
。values
是涉及的值。具有相同運算子的連續運算,例如a or b or c
,將被摺疊成一個具有多個值的節點。這不包括
not
,它是一個UnaryOp
。>>> print(ast.dump(ast.parse('x or y', mode='eval'), indent=4)) Expression( body=BoolOp( op=Or(), values=[ Name(id='x', ctx=Load()), Name(id='y', ctx=Load())]))
- class ast.Compare(left, ops, comparators)¶
兩個或多個值的比較。
left
是比較中的第一個值,ops
是運算子列表,而comparators
是比較中第一個元素之後的值列表。>>> print(ast.dump(ast.parse('1 <= a < 10', mode='eval'), indent=4)) Expression( body=Compare( left=Constant(value=1), ops=[ LtE(), Lt()], comparators=[ Name(id='a', ctx=Load()), Constant(value=10)]))
- class ast.Eq¶
- class ast.NotEq¶
- class ast.Lt¶
- class ast.LtE¶
- class ast.Gt¶
- class ast.GtE¶
- class ast.Is¶
- class ast.IsNot¶
- class ast.In¶
- class ast.NotIn¶
比較運算子標記。
- class ast.Call(func, args, keywords)¶
函式呼叫。
func
是函式,通常是一個Name
或Attribute
物件。關於引數args
包含按位置傳遞的引數列表。keywords
包含表示按關鍵字傳遞的引數的keyword
物件列表。
args
和keywords
引數是可選的,預設為空列表。>>> print(ast.dump(ast.parse('func(a, b=c, *d, **e)', mode='eval'), indent=4)) Expression( body=Call( func=Name(id='func', ctx=Load()), args=[ Name(id='a', ctx=Load()), Starred( value=Name(id='d', ctx=Load()), ctx=Load())], keywords=[ keyword( arg='b', value=Name(id='c', ctx=Load())), keyword( value=Name(id='e', ctx=Load()))]))
- class ast.keyword(arg, value)¶
函式呼叫或類定義的關鍵字引數。
arg
是引數名稱的原始字串,value
是要傳入的節點。
- class ast.IfExp(test, body, orelse)¶
一個諸如
a if b else c
的表示式。每個欄位都包含一個單獨的節點,因此在以下示例中,所有三個都是Name
節點。>>> print(ast.dump(ast.parse('a if b else c', mode='eval'), indent=4)) Expression( body=IfExp( test=Name(id='b', ctx=Load()), body=Name(id='a', ctx=Load()), orelse=Name(id='c', ctx=Load())))
- class ast.Attribute(value, attr, ctx)¶
屬性訪問,例如
d.keys
。value
是一個節點,通常是Name
。attr
是一個給出屬性名稱的裸字串,並且ctx
是Load
、Store
或Del
,具體取決於如何對屬性執行操作。>>> print(ast.dump(ast.parse('snake.colour', mode='eval'), indent=4)) Expression( body=Attribute( value=Name(id='snake', ctx=Load()), attr='colour', ctx=Load()))
- class ast.NamedExpr(target, value)¶
命名錶達式。此 AST 節點由賦值表示式運算子(也稱為海象運算子)生成。與
Assign
節點中第一個引數可以是多個節點不同,在這種情況下,target
和value
都必須是單個節點。>>> print(ast.dump(ast.parse('(x := 4)', mode='eval'), indent=4)) Expression( body=NamedExpr( target=Name(id='x', ctx=Store()), value=Constant(value=4)))
在 3.8 版本中新增。
下標¶
- class ast.Subscript(value, slice, ctx)¶
一個下標,例如
l[1]
。value
是下標物件(通常是序列或對映)。slice
是索引、切片或鍵。它可以是一個Tuple
並且包含一個Slice
。ctx
是Load
、Store
或Del
,具體取決於使用下標執行的操作。>>> print(ast.dump(ast.parse('l[1:2, 3]', mode='eval'), indent=4)) Expression( body=Subscript( value=Name(id='l', ctx=Load()), slice=Tuple( elts=[ Slice( lower=Constant(value=1), upper=Constant(value=2)), Constant(value=3)], ctx=Load()), ctx=Load()))
- class ast.Slice(lower, upper, step)¶
常規切片(形式為
lower:upper
或lower:upper:step
)。只能出現在Subscript
的 slice 欄位中,可以直接出現,也可以作為Tuple
的元素出現。>>> print(ast.dump(ast.parse('l[1:2]', mode='eval'), indent=4)) Expression( body=Subscript( value=Name(id='l', ctx=Load()), slice=Slice( lower=Constant(value=1), upper=Constant(value=2)), ctx=Load()))
推導式¶
- class ast.ListComp(elt, generators)¶
- class ast.SetComp(elt, generators)¶
- class ast.GeneratorExp(elt, generators)¶
- class ast.DictComp(key, value, generators)¶
列表和集合推導式、生成器表示式和字典推導式。
elt
(或key
和value
)是表示將為每個專案評估的部分的單個節點。generators
是comprehension
節點的列表。>>> print(ast.dump( ... ast.parse('[x for x in numbers]', mode='eval'), ... indent=4, ... )) Expression( body=ListComp( elt=Name(id='x', ctx=Load()), generators=[ comprehension( target=Name(id='x', ctx=Store()), iter=Name(id='numbers', ctx=Load()), is_async=0)])) >>> print(ast.dump( ... ast.parse('{x: x**2 for x in numbers}', mode='eval'), ... indent=4, ... )) Expression( body=DictComp( key=Name(id='x', ctx=Load()), value=BinOp( left=Name(id='x', ctx=Load()), op=Pow(), right=Constant(value=2)), generators=[ comprehension( target=Name(id='x', ctx=Store()), iter=Name(id='numbers', ctx=Load()), is_async=0)])) >>> print(ast.dump( ... ast.parse('{x for x in numbers}', mode='eval'), ... indent=4, ... )) Expression( body=SetComp( elt=Name(id='x', ctx=Load()), generators=[ comprehension( target=Name(id='x', ctx=Store()), iter=Name(id='numbers', ctx=Load()), is_async=0)]))
- class ast.comprehension(target, iter, ifs, is_async)¶
推導式中的一個
for
子句。target
是用於每個元素的引用 - 通常是Name
或Tuple
節點。iter
是要迭代的物件。ifs
是測試表達式的列表:每個for
子句可以有多個ifs
。is_async
表示推導式是非同步的(使用async for
而不是for
)。該值是一個整數(0 或 1)。>>> print(ast.dump(ast.parse('[ord(c) for line in file for c in line]', mode='eval'), ... indent=4)) # Multiple comprehensions in one. Expression( body=ListComp( elt=Call( func=Name(id='ord', ctx=Load()), args=[ Name(id='c', ctx=Load())]), generators=[ comprehension( target=Name(id='line', ctx=Store()), iter=Name(id='file', ctx=Load()), is_async=0), comprehension( target=Name(id='c', ctx=Store()), iter=Name(id='line', ctx=Load()), is_async=0)])) >>> print(ast.dump(ast.parse('(n**2 for n in it if n>5 if n<10)', mode='eval'), ... indent=4)) # generator comprehension Expression( body=GeneratorExp( elt=BinOp( left=Name(id='n', ctx=Load()), op=Pow(), right=Constant(value=2)), generators=[ comprehension( target=Name(id='n', ctx=Store()), iter=Name(id='it', ctx=Load()), ifs=[ Compare( left=Name(id='n', ctx=Load()), ops=[ Gt()], comparators=[ Constant(value=5)]), Compare( left=Name(id='n', ctx=Load()), ops=[ Lt()], comparators=[ Constant(value=10)])], is_async=0)])) >>> print(ast.dump(ast.parse('[i async for i in soc]', mode='eval'), ... indent=4)) # Async comprehension Expression( body=ListComp( elt=Name(id='i', ctx=Load()), generators=[ comprehension( target=Name(id='i', ctx=Store()), iter=Name(id='soc', ctx=Load()), is_async=1)]))
語句¶
- class ast.Assign(targets, value, type_comment)¶
賦值。
targets
是一個節點列表,value
是一個單獨的節點。targets
中的多個節點表示將相同的值分配給每個節點。解包透過在targets
中放置一個Tuple
或List
來表示。- type_comment¶
type_comment
是一個可選字串,其中包含作為註釋的型別註解。
>>> print(ast.dump(ast.parse('a = b = 1'), indent=4)) # Multiple assignment Module( body=[ Assign( targets=[ Name(id='a', ctx=Store()), Name(id='b', ctx=Store())], value=Constant(value=1))]) >>> print(ast.dump(ast.parse('a,b = c'), indent=4)) # Unpacking Module( body=[ Assign( targets=[ Tuple( elts=[ Name(id='a', ctx=Store()), Name(id='b', ctx=Store())], ctx=Store())], value=Name(id='c', ctx=Load()))])
- class ast.AnnAssign(target, annotation, value, simple)¶
帶有型別註解的賦值。
target
是一個單獨的節點,可以是Name
、Attribute
或Subscript
。annotation
是註解,例如Constant
或Name
節點。value
是一個可選的單獨節點。simple
始終為 0(表示“複雜”目標)或 1(表示“簡單”目標)。“簡單”目標僅由一個不出現在括號之間的Name
節點組成;所有其他目標都被認為是複雜的。只有簡單的目標會出現在模組和類的__annotations__
字典中。>>> print(ast.dump(ast.parse('c: int'), indent=4)) Module( body=[ AnnAssign( target=Name(id='c', ctx=Store()), annotation=Name(id='int', ctx=Load()), simple=1)]) >>> print(ast.dump(ast.parse('(a): int = 1'), indent=4)) # Annotation with parenthesis Module( body=[ AnnAssign( target=Name(id='a', ctx=Store()), annotation=Name(id='int', ctx=Load()), value=Constant(value=1), simple=0)]) >>> print(ast.dump(ast.parse('a.b: int'), indent=4)) # Attribute annotation Module( body=[ AnnAssign( target=Attribute( value=Name(id='a', ctx=Load()), attr='b', ctx=Store()), annotation=Name(id='int', ctx=Load()), simple=0)]) >>> print(ast.dump(ast.parse('a[1]: int'), indent=4)) # Subscript annotation Module( body=[ AnnAssign( target=Subscript( value=Name(id='a', ctx=Load()), slice=Constant(value=1), ctx=Store()), annotation=Name(id='int', ctx=Load()), simple=0)])
- class ast.AugAssign(target, op, value)¶
增廣賦值,例如
a += 1
。在以下示例中,target
是x
的Name
節點(帶有Store
上下文),op
是Add
,value
是值為 1 的Constant
。與
Assign
的目標不同,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))])
- class ast.Raise(exc, cause)¶
一個
raise
語句。exc
是要引發的異常物件,通常是Call
或Name
,或者對於獨立的raise
來說是None
。cause
是raise x from y
中可選的y
部分。>>> print(ast.dump(ast.parse('raise x from y'), indent=4)) Module( body=[ Raise( exc=Name(id='x', ctx=Load()), cause=Name(id='y', ctx=Load()))])
- class ast.Assert(test, msg)¶
一個斷言。
test
儲存條件,例如Compare
節點。msg
儲存失敗訊息。>>> print(ast.dump(ast.parse('assert x,y'), indent=4)) Module( body=[ Assert( test=Name(id='x', ctx=Load()), msg=Name(id='y', ctx=Load()))])
- class ast.Delete(targets)¶
表示
del
語句。targets
是節點列表,例如Name
、Attribute
或Subscript
節點。>>> print(ast.dump(ast.parse('del x,y,z'), indent=4)) Module( body=[ Delete( targets=[ Name(id='x', ctx=Del()), Name(id='y', ctx=Del()), Name(id='z', ctx=Del())])])
- class ast.Pass¶
一個
pass
語句。>>> print(ast.dump(ast.parse('pass'), indent=4)) Module( body=[ Pass()])
- class ast.TypeAlias(name, type_params, value)¶
透過
type
語句建立的類型別名。name
是別名的名稱,type_params
是 型別引數 的列表,value
是類型別名的值。>>> print(ast.dump(ast.parse('type Alias = int'), indent=4)) Module( body=[ TypeAlias( name=Name(id='Alias', ctx=Store()), value=Name(id='int', ctx=Load()))])
3.12 版本中新增。
其他僅適用於函式或迴圈內部的語句將在其他章節中描述。
匯入¶
- class ast.Import(names)¶
一個匯入語句。
names
是alias
節點的列表。>>> print(ast.dump(ast.parse('import x,y,z'), indent=4)) Module( body=[ Import( names=[ alias(name='x'), alias(name='y'), alias(name='z')])])
- class ast.ImportFrom(module, names, level)¶
表示
from x import y
。module
是 'from' 名稱的原始字串,不帶任何前導點,或者對於諸如from . import foo
之類的語句,則為None
。level
是一個整數,表示相對匯入的級別(0 表示絕對匯入)。>>> print(ast.dump(ast.parse('from y import x,y,z'), indent=4)) Module( body=[ ImportFrom( module='y', names=[ alias(name='x'), alias(name='y'), alias(name='z')], level=0)])
- class ast.alias(name, asname)¶
兩個引數都是名稱的原始字串。 如果要使用常規名稱,則
asname
可以為None
。>>> print(ast.dump(ast.parse('from ..foo.bar import a as b, c'), indent=4)) Module( body=[ ImportFrom( module='foo.bar', names=[ alias(name='a', asname='b'), alias(name='c')], level=2)])
控制流¶
注意
諸如 else
之類的可選子句,如果不存在,則儲存為空列表。
- class ast.If(test, body, orelse)¶
一個
if
語句。test
儲存單個節點,例如Compare
節點。body
和orelse
各自儲存一個節點列表。elif
子句在 AST 中沒有特殊的表示形式,而是作為前一個orelse
部分中的額外If
節點出現。>>> print(ast.dump(ast.parse(""" ... if x: ... ... ... elif y: ... ... ... else: ... ... ... """), indent=4)) Module( body=[ If( test=Name(id='x', ctx=Load()), body=[ Expr( value=Constant(value=Ellipsis))], orelse=[ If( test=Name(id='y', ctx=Load()), body=[ Expr( value=Constant(value=Ellipsis))], orelse=[ Expr( value=Constant(value=Ellipsis))])])])
- class ast.For(target, iter, body, orelse, type_comment)¶
一個
for
迴圈。target
儲存迴圈賦值的變數,作為單個Name
、Tuple
、List
、Attribute
或Subscript
節點。iter
儲存要迴圈的專案,同樣作為單個節點。body
和orelse
包含要執行的節點列表。如果迴圈正常完成而不是透過break
語句完成,則執行orelse
中的節點。- type_comment¶
type_comment
是一個可選字串,其中包含作為註釋的型別註解。
>>> print(ast.dump(ast.parse(""" ... for x in y: ... ... ... else: ... ... ... """), indent=4)) Module( body=[ For( target=Name(id='x', ctx=Store()), iter=Name(id='y', ctx=Load()), body=[ Expr( value=Constant(value=Ellipsis))], orelse=[ Expr( value=Constant(value=Ellipsis))])])
- class ast.While(test, body, orelse)¶
一個
while
迴圈。test
儲存條件,例如Compare
節點。>> print(ast.dump(ast.parse(""" ... while x: ... ... ... else: ... ... ... """), indent=4)) Module( body=[ While( test=Name(id='x', ctx=Load()), body=[ Expr( value=Constant(value=Ellipsis))], orelse=[ Expr( value=Constant(value=Ellipsis))])])
- class ast.Break¶
- class ast.Continue¶
break
和continue
語句。>>> print(ast.dump(ast.parse("""\ ... for a in b: ... if a > 5: ... break ... else: ... continue ... ... """), indent=4)) Module( body=[ For( target=Name(id='a', ctx=Store()), iter=Name(id='b', ctx=Load()), body=[ If( test=Compare( left=Name(id='a', ctx=Load()), ops=[ Gt()], comparators=[ Constant(value=5)]), body=[ Break()], orelse=[ Continue()])])])
- class ast.Try(body, handlers, orelse, finalbody)¶
try
程式碼塊。所有屬性都是要執行的節點列表,除了handlers
,它是一個ExceptHandler
節點的列表。>>> print(ast.dump(ast.parse(""" ... try: ... ... ... except Exception: ... ... ... except OtherException as e: ... ... ... else: ... ... ... finally: ... ... ... """), indent=4)) Module( body=[ Try( body=[ Expr( value=Constant(value=Ellipsis))], handlers=[ ExceptHandler( type=Name(id='Exception', ctx=Load()), body=[ Expr( value=Constant(value=Ellipsis))]), ExceptHandler( type=Name(id='OtherException', ctx=Load()), name='e', body=[ Expr( value=Constant(value=Ellipsis))])], orelse=[ Expr( value=Constant(value=Ellipsis))], finalbody=[ Expr( value=Constant(value=Ellipsis))])])
- class ast.TryStar(body, handlers, orelse, finalbody)¶
後跟
except*
子句的try
程式碼塊。這些屬性與Try
的相同,但handlers
中的ExceptHandler
節點被解釋為except*
程式碼塊,而不是except
。>>> print(ast.dump(ast.parse(""" ... try: ... ... ... except* Exception: ... ... ... """), indent=4)) Module( body=[ TryStar( body=[ Expr( value=Constant(value=Ellipsis))], handlers=[ ExceptHandler( type=Name(id='Exception', ctx=Load()), body=[ Expr( value=Constant(value=Ellipsis))])])])
在 3.11 版本中新增。
- class ast.ExceptHandler(type, name, body)¶
單個
except
子句。type
是它將匹配的異常型別,通常是一個Name
節點(或者對於捕獲所有異常的except:
子句,則為None
)。name
是用於儲存異常的原始字串名稱,如果該子句沒有as foo
,則為None
。body
是節點列表。>>> print(ast.dump(ast.parse("""\ ... try: ... a + 1 ... except TypeError: ... pass ... """), indent=4)) Module( body=[ Try( body=[ Expr( value=BinOp( left=Name(id='a', ctx=Load()), op=Add(), right=Constant(value=1)))], handlers=[ ExceptHandler( type=Name(id='TypeError', ctx=Load()), body=[ Pass()])])])
- class ast.With(items, body, type_comment)¶
with
程式碼塊。items
是表示上下文管理器的withitem
節點列表,body
是上下文內部的縮排程式碼塊。- type_comment¶
type_comment
是一個可選字串,其中包含作為註釋的型別註解。
- class ast.withitem(context_expr, optional_vars)¶
with
程式碼塊中的單個上下文管理器。context_expr
是上下文管理器,通常是Call
節點。optional_vars
是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())]))])])
模式匹配¶
- class ast.Match(subject, cases)¶
match
語句。subject
儲存匹配的主題(正在與 case 進行匹配的物件),cases
包含一個match_case
節點的迭代器,其中包含不同的 case。在 3.10 版本中新增。
- class ast.match_case(pattern, guard, body)¶
match
語句中的單個 case 模式。pattern
包含將與主題進行匹配的匹配模式。請注意,為模式生成的AST
節點與為表示式生成的節點不同,即使它們共享相同的語法。guard
屬性包含一個表示式,如果模式與主題匹配,則會對其進行求值。如果模式匹配且計算 guard 表示式的結果為 true,則
body
包含要執行的節點列表。>>> print(ast.dump(ast.parse(""" ... match x: ... case [x] if x>0: ... ... ... case tuple(): ... ... ... """), indent=4)) Module( body=[ Match( subject=Name(id='x', ctx=Load()), cases=[ match_case( pattern=MatchSequence( patterns=[ MatchAs(name='x')]), guard=Compare( left=Name(id='x', ctx=Load()), ops=[ Gt()], comparators=[ Constant(value=0)]), body=[ Expr( value=Constant(value=Ellipsis))]), match_case( pattern=MatchClass( cls=Name(id='tuple', ctx=Load())), body=[ Expr( value=Constant(value=Ellipsis))])])])
在 3.10 版本中新增。
- class ast.MatchValue(value)¶
透過相等比較的匹配字面值或值模式。
value
是一個表示式節點。允許的值節點如 match 語句文件中所述受到限制。如果匹配主題等於已評估的值,則此模式成功。>>> print(ast.dump(ast.parse(""" ... match x: ... case "Relevant": ... ... ... """), indent=4)) Module( body=[ Match( subject=Name(id='x', ctx=Load()), cases=[ match_case( pattern=MatchValue( value=Constant(value='Relevant')), body=[ Expr( value=Constant(value=Ellipsis))])])])
在 3.10 版本中新增。
- class ast.MatchSingleton(value)¶
透過身份比較的匹配字面值模式。
value
是要比較的單例:None
、True
或False
。如果匹配主題是給定的常量,則此模式成功。>>> print(ast.dump(ast.parse(""" ... match x: ... case None: ... ... ... """), indent=4)) Module( body=[ Match( subject=Name(id='x', ctx=Load()), cases=[ match_case( pattern=MatchSingleton(value=None), body=[ Expr( value=Constant(value=Ellipsis))])])])
在 3.10 版本中新增。
- class ast.MatchSequence(patterns)¶
匹配序列模式。如果主題是序列,則
patterns
包含要與主題元素匹配的模式。如果其中一個子模式是MatchStar
節點,則匹配可變長度序列,否則匹配固定長度序列。>>> print(ast.dump(ast.parse(""" ... match x: ... case [1, 2]: ... ... ... """), indent=4)) Module( body=[ Match( subject=Name(id='x', ctx=Load()), cases=[ match_case( pattern=MatchSequence( patterns=[ MatchValue( value=Constant(value=1)), MatchValue( value=Constant(value=2))]), body=[ Expr( value=Constant(value=Ellipsis))])])])
在 3.10 版本中新增。
- class ast.MatchStar(name)¶
在可變長度匹配序列模式中,匹配序列的其餘部分。如果
name
不是None
,則如果整個序列模式成功,則將包含剩餘序列元素的列表繫結到該名稱。>>> print(ast.dump(ast.parse(""" ... match x: ... case [1, 2, *rest]: ... ... ... case [*_]: ... ... ... """), indent=4)) Module( body=[ Match( subject=Name(id='x', ctx=Load()), cases=[ match_case( pattern=MatchSequence( patterns=[ MatchValue( value=Constant(value=1)), MatchValue( value=Constant(value=2)), MatchStar(name='rest')]), body=[ Expr( value=Constant(value=Ellipsis))]), match_case( pattern=MatchSequence( patterns=[ MatchStar()]), body=[ Expr( value=Constant(value=Ellipsis))])])])
在 3.10 版本中新增。
- class ast.MatchMapping(keys, patterns, rest)¶
一個匹配對映模式。
keys
是表示式節點的序列。patterns
是對應的模式節點序列。rest
是一個可選的名稱,可以指定用於捕獲剩餘的對映元素。 允許的鍵表示式受匹配語句文件中描述的限制。如果主題是一個對映,所有計算出的鍵表示式都存在於該對映中,並且每個鍵對應的值與對應的子模式匹配,則此模式成功。如果
rest
不是None
,則當整體對映模式成功時,包含剩餘對映元素的字典將繫結到該名稱。>>> print(ast.dump(ast.parse(""" ... match x: ... case {1: _, 2: _}: ... ... ... case {**rest}: ... ... ... """), indent=4)) Module( body=[ Match( subject=Name(id='x', ctx=Load()), cases=[ match_case( pattern=MatchMapping( keys=[ Constant(value=1), Constant(value=2)], patterns=[ MatchAs(), MatchAs()]), body=[ Expr( value=Constant(value=Ellipsis))]), match_case( pattern=MatchMapping(rest='rest'), body=[ Expr( value=Constant(value=Ellipsis))])])])
在 3.10 版本中新增。
- class ast.MatchClass(cls, patterns, kwd_attrs, kwd_patterns)¶
一個匹配類模式。
cls
是一個表示式,給出要匹配的名義類。patterns
是要針對類定義的模式匹配屬性序列進行匹配的模式節點序列。kwd_attrs
是要匹配的其他屬性序列(在類模式中指定為關鍵字引數),kwd_patterns
是相應的模式(在類模式中指定為關鍵字值)。如果主題是指定類的例項,所有位置模式都與相應的類定義屬性匹配,並且任何指定的關鍵字屬性都與它們對應的模式匹配,則此模式成功。
注意:類可以定義一個返回 self 的屬性,以便將模式節點與正在匹配的例項進行匹配。如匹配語句文件中所述,一些內建型別也以這種方式進行匹配。
>>> print(ast.dump(ast.parse(""" ... match x: ... case Point2D(0, 0): ... ... ... case Point3D(x=0, y=0, z=0): ... ... ... """), indent=4)) Module( body=[ Match( subject=Name(id='x', ctx=Load()), cases=[ match_case( pattern=MatchClass( cls=Name(id='Point2D', ctx=Load()), patterns=[ MatchValue( value=Constant(value=0)), MatchValue( value=Constant(value=0))]), body=[ Expr( value=Constant(value=Ellipsis))]), match_case( pattern=MatchClass( cls=Name(id='Point3D', ctx=Load()), kwd_attrs=[ 'x', 'y', 'z'], kwd_patterns=[ MatchValue( value=Constant(value=0)), MatchValue( value=Constant(value=0)), MatchValue( value=Constant(value=0))]), body=[ Expr( value=Constant(value=Ellipsis))])])])
在 3.10 版本中新增。
- class ast.MatchAs(pattern, name)¶
一個匹配“as-pattern”,捕獲模式或萬用字元模式。
pattern
包含要與主題匹配的匹配模式。如果模式是None
,則該節點表示捕獲模式(即裸名稱),並且將始終成功。name
屬性包含如果模式成功將繫結的名稱。如果name
是None
,則pattern
也必須是None
,並且該節點表示萬用字元模式。>>> print(ast.dump(ast.parse(""" ... match x: ... case [x] as y: ... ... ... case _: ... ... ... """), indent=4)) Module( body=[ Match( subject=Name(id='x', ctx=Load()), cases=[ match_case( pattern=MatchAs( pattern=MatchSequence( patterns=[ MatchAs(name='x')]), name='y'), body=[ Expr( value=Constant(value=Ellipsis))]), match_case( pattern=MatchAs(), body=[ Expr( value=Constant(value=Ellipsis))])])])
在 3.10 版本中新增。
- class ast.MatchOr(patterns)¶
一個匹配“或-模式”。或-模式依次將其每個子模式與主題進行匹配,直到一個成功。然後,或-模式被視為成功。如果沒有一個子模式成功,則或-模式失敗。
patterns
屬性包含將與主題匹配的匹配模式節點列表。>>> print(ast.dump(ast.parse(""" ... match x: ... case [x] | (y): ... ... ... """), indent=4)) Module( body=[ Match( subject=Name(id='x', ctx=Load()), cases=[ match_case( pattern=MatchOr( patterns=[ MatchSequence( patterns=[ MatchAs(name='x')]), MatchAs(name='y')]), body=[ Expr( value=Constant(value=Ellipsis))])])])
在 3.10 版本中新增。
型別引數¶
型別引數 可以存在於類、函式和類型別名上。
- class ast.TypeVar(name, bound, default_value)¶
一個
typing.TypeVar
。name
是型別變數的名稱。bound
是邊界或約束(如果有)。如果bound
是Tuple
,則表示約束;否則表示邊界。default_value
是預設值;如果TypeVar
沒有預設值,則此屬性將設定為None
。>>> print(ast.dump(ast.parse("type Alias[T: int = bool] = list[T]"), indent=4)) Module( body=[ TypeAlias( name=Name(id='Alias', ctx=Store()), type_params=[ TypeVar( name='T', bound=Name(id='int', ctx=Load()), default_value=Name(id='bool', ctx=Load()))], value=Subscript( value=Name(id='list', ctx=Load()), slice=Name(id='T', ctx=Load()), ctx=Load()))])
3.12 版本中新增。
在 3.13 版本中更改: 添加了 default_value 引數。
- class ast.ParamSpec(name, default_value)¶
一個
typing.ParamSpec
。name
是引數規範的名稱。default_value
是預設值;如果ParamSpec
沒有預設值,則此屬性將設定為None
。>>> print(ast.dump(ast.parse("type Alias[**P = [int, str]] = Callable[P, int]"), indent=4)) Module( body=[ TypeAlias( name=Name(id='Alias', ctx=Store()), type_params=[ ParamSpec( name='P', default_value=List( elts=[ Name(id='int', ctx=Load()), Name(id='str', ctx=Load())], ctx=Load()))], value=Subscript( value=Name(id='Callable', ctx=Load()), slice=Tuple( elts=[ Name(id='P', ctx=Load()), Name(id='int', ctx=Load())], ctx=Load()), ctx=Load()))])
3.12 版本中新增。
在 3.13 版本中更改: 添加了 default_value 引數。
- class ast.TypeVarTuple(name, default_value)¶
一個
typing.TypeVarTuple
。name
是型別變數元組的名稱。default_value
是預設值;如果TypeVarTuple
沒有預設值,則此屬性將設定為None
。>>> print(ast.dump(ast.parse("type Alias[*Ts = ()] = tuple[*Ts]"), indent=4)) Module( body=[ TypeAlias( name=Name(id='Alias', ctx=Store()), type_params=[ TypeVarTuple( name='Ts', default_value=Tuple(ctx=Load()))], value=Subscript( value=Name(id='tuple', ctx=Load()), slice=Tuple( elts=[ Starred( value=Name(id='Ts', ctx=Load()), ctx=Load())], ctx=Load()), ctx=Load()))])
3.12 版本中新增。
在 3.13 版本中更改: 添加了 default_value 引數。
函式和類定義¶
- class ast.FunctionDef(name, args, body, decorator_list, returns, type_comment, type_params)¶
一個函式定義。
name
是函式名稱的原始字串。args
是一個arguments
節點。body
是函式內部的節點列表。decorator_list
是要應用的裝飾器列表,按最外層優先儲存(即,列表中的第一個將最後應用)。returns
是返回註釋。type_params
是 型別引數 的列表。
- type_comment¶
type_comment
是一個可選字串,其中包含作為註釋的型別註解。
在 3.12 版本中更改: 添加了
type_params
。
- class ast.Lambda(args, body)¶
lambda
是一個最小的函式定義,可以在表示式內部使用。 與FunctionDef
不同,body
包含一個節點。>>> print(ast.dump(ast.parse('lambda x,y: ...'), indent=4)) Module( body=[ Expr( value=Lambda( args=arguments( args=[ arg(arg='x'), arg(arg='y')]), body=Constant(value=Ellipsis)))])
- class ast.arguments(posonlyargs, args, vararg, kwonlyargs, kw_defaults, kwarg, defaults)¶
函式的引數。
- class ast.arg(arg, annotation, type_comment)¶
列表中的單個引數。
arg
是引數名稱的原始字串;annotation
是其註解,例如Name
節點。- type_comment¶
type_comment
是一個可選字串,其中包含型別註解作為註釋。
>>> print(ast.dump(ast.parse("""\ ... @decorator1 ... @decorator2 ... def f(a: 'annotation', b=1, c=2, *d, e, f=3, **g) -> 'return annotation': ... pass ... """), indent=4)) Module( body=[ FunctionDef( name='f', args=arguments( args=[ arg( arg='a', annotation=Constant(value='annotation')), arg(arg='b'), arg(arg='c')], vararg=arg(arg='d'), kwonlyargs=[ arg(arg='e'), arg(arg='f')], kw_defaults=[ None, Constant(value=3)], kwarg=arg(arg='g'), defaults=[ Constant(value=1), Constant(value=2)]), body=[ Pass()], decorator_list=[ Name(id='decorator1', ctx=Load()), Name(id='decorator2', ctx=Load())], returns=Constant(value='return annotation'))])
- class ast.Return(value)¶
return
語句。>>> print(ast.dump(ast.parse('return 4'), indent=4)) Module( body=[ Return( value=Constant(value=4))])
- class ast.Yield(value)¶
- class ast.YieldFrom(value)¶
yield
或yield from
表示式。 由於這些是表示式,如果未使用返回的值,則必須將其包裝在Expr
節點中。>>> print(ast.dump(ast.parse('yield x'), indent=4)) Module( body=[ Expr( value=Yield( value=Name(id='x', ctx=Load())))]) >>> print(ast.dump(ast.parse('yield from x'), indent=4)) Module( body=[ Expr( value=YieldFrom( value=Name(id='x', ctx=Load())))])
- class ast.Global(names)¶
- class ast.Nonlocal(names)¶
global
和nonlocal
語句。names
是原始字串的列表。>>> print(ast.dump(ast.parse('global x,y,z'), indent=4)) Module( body=[ Global( names=[ 'x', 'y', 'z'])]) >>> print(ast.dump(ast.parse('nonlocal x,y,z'), indent=4)) Module( body=[ Nonlocal( names=[ 'x', 'y', 'z'])])
- class ast.ClassDef(name, bases, keywords, body, decorator_list, type_params)¶
類定義。
name
是類名稱的原始字串。bases
是顯式指定的基類的節點列表。keywords
是keyword
節點的列表,主要用於 “metaclass”。根據 PEP 3115,其他關鍵字將傳遞給元類。body
是表示類定義中程式碼的節點列表。decorator_list
是節點列表,與FunctionDef
中的類似。type_params
是 型別引數 的列表。
>>> print(ast.dump(ast.parse("""\ ... @decorator1 ... @decorator2 ... class Foo(base1, base2, metaclass=meta): ... pass ... """), indent=4)) Module( body=[ ClassDef( name='Foo', bases=[ Name(id='base1', ctx=Load()), Name(id='base2', ctx=Load())], keywords=[ keyword( arg='metaclass', value=Name(id='meta', ctx=Load()))], body=[ Pass()], decorator_list=[ Name(id='decorator1', ctx=Load()), Name(id='decorator2', ctx=Load())])])
在 3.12 版本中更改: 添加了
type_params
。
Async 和 await¶
- class ast.AsyncFunctionDef(name, args, body, decorator_list, returns, type_comment, type_params)¶
async def
函式定義。 具有與FunctionDef
相同的欄位。在 3.12 版本中更改: 添加了
type_params
。
- class ast.Await(value)¶
await
表示式。value
是它等待的內容。 僅在AsyncFunctionDef
的主體中有效。
>>> print(ast.dump(ast.parse("""\
... async def f():
... await other_func()
... """), indent=4))
Module(
body=[
AsyncFunctionDef(
name='f',
args=arguments(),
body=[
Expr(
value=Await(
value=Call(
func=Name(id='other_func', ctx=Load()))))])])
- class ast.AsyncFor(target, iter, body, orelse, type_comment)¶
- class ast.AsyncWith(items, body, type_comment)¶
async for
迴圈和async with
上下文管理器。 它們分別具有與For
和With
相同的欄位。 僅在AsyncFunctionDef
的主體中有效。
注意
當字串由 ast.parse()
解析時,返回的樹上的運算子節點(ast.operator
、ast.unaryop
、ast.cmpop
、ast.boolop
和 ast.expr_context
的子類)將是單例。對其中一個的更改將反映在相同值的所有其他出現中(例如 ast.Add
)。
ast
助手¶
除了節點類之外,ast
模組還定義了以下用於遍歷抽象語法樹的實用函式和類
- ast.parse(source, filename='<unknown>', mode='exec', *, type_comments=False, feature_version=None, optimize=-1)¶
將原始碼解析為 AST 節點。等效於
compile(source, filename, mode, flags=FLAGS_VALUE, optimize=optimize)
,其中FLAGS_VALUE
在optimize <= 0
時為ast.PyCF_ONLY_AST
,否則為ast.PyCF_OPTIMIZED_AST
。如果給定
type_comments=True
,則會修改解析器以檢查並返回 PEP 484 和 PEP 526 指定的型別註釋。這等效於將ast.PyCF_TYPE_COMMENTS
新增到傳遞給compile()
的標誌。這將報告型別註釋放置錯誤的語法錯誤。如果沒有此標誌,型別註釋將被忽略,並且選定 AST 節點上的type_comment
欄位將始終為None
。此外,# type: ignore
註釋的位置將作為Module
的type_ignores
屬性返回(否則它始終是一個空列表)。此外,如果
mode
是'func_type'
,則輸入語法將被修改以對應於 PEP 484 “簽名型別註釋”,例如(str, int) -> List[str]
。將
feature_version
設定為元組(major, minor)
將導致“盡力而為”地嘗試使用該 Python 版本的語法進行解析。例如,設定feature_version=(3, 9)
將嘗試禁止解析match
語句。目前,major
必須等於3
。支援的最低版本是(3, 7)
(並且這可能在未來的 Python 版本中增加);最高版本是sys.version_info[0:2]
。“盡力而為”的嘗試意味著不能保證解析(或解析的成功)與在與feature_version
對應的 Python 版本上執行時相同。如果原始碼包含空字元(
\0
),則會引發ValueError
。警告
請注意,成功將原始碼解析為 AST 物件並不能保證提供的原始碼是有效的 Python 程式碼,可以執行,因為編譯步驟可能會引發進一步的
SyntaxError
異常。例如,原始碼return 42
為返回語句生成一個有效的 AST 節點,但它不能單獨編譯(它需要位於函式節點內)。特別是,
ast.parse()
不會進行任何作用域檢查,而編譯步驟會進行這些檢查。警告
由於 Python 的 AST 編譯器中的堆疊深度限制,可以使用足夠大/複雜的字串使 Python 直譯器崩潰。
在 3.8 版本中更改: 添加了
type_comments
、mode='func_type'
和feature_version
。在 3.13 版本中更改:
feature_version
的最低支援版本現在是(3, 7)
。添加了optimize
引數。
- ast.unparse(ast_obj)¶
解析
ast.AST
物件並生成一個字串,其中包含如果使用ast.parse()
解析回來則會產生等效ast.AST
物件的程式碼。警告
生成的程式碼字串不一定等於生成
ast.AST
物件的原始程式碼(沒有任何編譯器最佳化,例如常量元組/凍結集合)。警告
嘗試解析高度複雜的表示式會導致
RecursionError
。在 3.9 版本中新增。
- ast.literal_eval(node_or_string)¶
評估表示式節點或僅包含 Python 字面值或容器顯示的字串。提供的字串或節點可能只包含以下 Python 字面值結構:字串、位元組、數字、元組、列表、字典、集合、布林值、
None
和Ellipsis
。這可用於評估包含 Python 值的字串,而無需自己解析這些值。它無法評估任意複雜的表示式,例如涉及運算子或索引的表示式。
過去,此函式被記錄為“安全”,但沒有定義其含義。這是具有誤導性的。此函式專門設計為不執行 Python 程式碼,這與更通用的
eval()
不同。沒有名稱空間、沒有名稱查詢或呼叫能力。但是它並非沒有攻擊風險:相對較小的輸入可能會導致記憶體耗盡或 C 堆疊耗盡,從而導致程序崩潰。某些輸入還可能導致過多的 CPU 消耗拒絕服務。因此,不建議在不受信任的資料上呼叫它。警告
由於 Python 的 AST 編譯器中的堆疊深度限制,可能會使 Python 直譯器崩潰。
它可能會根據格式錯誤的輸入引發
ValueError
、TypeError
、SyntaxError
、MemoryError
和RecursionError
。在 3.2 版本中更改: 現在允許位元組和集合字面量。
在 3.9 版本中更改: 現在支援使用
'set()'
建立空集合。在 3.10 版本中更改: 對於字串輸入,現在會去除前導空格和製表符。
- ast.get_docstring(node, clean=True)¶
返回給定 *node* 的文件字串(必須是
FunctionDef
、AsyncFunctionDef
、ClassDef
或Module
節點),如果沒有文件字串,則返回None
。如果 *clean* 為 true,則使用inspect.cleandoc()
清理文件字串的縮排。在 3.5 版本中更改: 現在支援
AsyncFunctionDef
。
- ast.get_source_segment(source, node, *, padded=False)¶
獲取生成 *node* 的 *source* 的原始碼片段。如果缺少一些位置資訊(
lineno
、end_lineno
、col_offset
或end_col_offset
),則返回None
。如果 *padded* 為
True
,則多行語句的第一行將用空格填充,以匹配其原始位置。在 3.8 版本中新增。
- ast.fix_missing_locations(node)¶
當您使用
compile()
編譯節點樹時,編譯器期望每個支援它們的節點都有lineno
和col_offset
屬性。對於生成的節點,填充這些屬性相當繁瑣,因此此輔助函式透過將它們設定為父節點的值,以遞迴方式為尚未設定這些屬性的節點新增這些屬性。它從 *node* 開始遞迴工作。
- ast.increment_lineno(node, n=1)¶
將從 *node* 開始的樹中每個節點的行號和結束行號遞增 *n*。 這對於將“程式碼移動”到檔案中的不同位置很有用。
- ast.copy_location(new_node, old_node)¶
如果可能,將源位置(
lineno
、col_offset
、end_lineno
和end_col_offset
)從 *old_node* 複製到 *new_node*,並返回 *new_node*。
- ast.iter_fields(node)¶
為 *node* 中存在的每個
node._fields
中的欄位生成一個(欄位名, 值)
的元組。
- ast.iter_child_nodes(node)¶
生成 *node* 的所有直接子節點,即所有為節點的欄位以及所有為節點列表的欄位項。
- ast.walk(node)¶
以未指定的順序遞迴生成從 *node* 開始的樹中的所有後代節點(包括 *node* 本身)。如果您只想就地修改節點而不關心上下文,這將非常有用。
- class ast.NodeVisitor¶
一個節點訪問者基類,它遍歷抽象語法樹,併為找到的每個節點呼叫一個訪問者函式。此函式可能會返回一個值,該值由
visit()
方法轉發。這個類旨在被子類化,子類新增訪問者方法。
- visit(node)¶
訪問一個節點。預設實現會呼叫名為
self.visit_classname
的方法,其中 *classname* 是節點類的名稱,如果該方法不存在,則呼叫generic_visit()
。
- generic_visit(node)¶
此訪問器在節點的所有子節點上呼叫
visit()
。請注意,除非訪問器呼叫
generic_visit()
或自行訪問,否則具有自定義訪問器方法的節點的子節點將不會被訪問。
- visit_Constant(node)¶
處理所有常量節點。
如果您想在遍歷期間對節點應用更改,請不要使用
NodeVisitor
。為此,存在一個特殊的訪問器 (NodeTransformer
),它允許修改。3.8 版本後已棄用: 方法
visit_Num()
、visit_Str()
、visit_Bytes()
、visit_NameConstant()
和visit_Ellipsis()
現在已棄用,並且在未來的 Python 版本中將不會被呼叫。 新增visit_Constant()
方法來處理所有常量節點。
- class ast.NodeTransformer¶
一個
NodeVisitor
子類,它遍歷抽象語法樹並允許修改節點。NodeTransformer
將遍歷 AST 並使用訪問器方法的返回值來替換或刪除舊節點。如果訪問器方法的返回值是None
,則該節點將從其位置移除,否則它將被返回值替換。返回值可能是原始節點,在這種情況下不會發生替換。這是一個示例轉換器,它將所有出現的名稱查詢(
foo
)重寫為data['foo']
class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load()), slice=Constant(value=node.id), ctx=node.ctx )
請記住,如果您正在操作的節點具有子節點,則必須自己轉換子節點或先為該節點呼叫
generic_visit()
方法。對於屬於語句集合的節點(適用於所有語句節點),訪問器還可以返回節點列表,而不僅僅是單個節點。
如果
NodeTransformer
引入了新的節點(這些節點不是原始樹的一部分),而沒有給它們位置資訊(例如lineno
),則應使用新的子樹呼叫fix_missing_locations()
,以重新計算位置資訊tree = ast.parse('foo', mode='eval') new_tree = fix_missing_locations(RewriteName().visit(tree))
通常您像這樣使用轉換器
node = YourTransformer().visit(node)
- ast.dump(node, annotate_fields=True, include_attributes=False, *, indent=None, show_empty=False)¶
返回 node 中樹的格式化轉儲。這主要用於除錯目的。如果 annotate_fields 為 true(預設情況下),則返回的字串將顯示欄位的名稱和值。如果 annotate_fields 為 false,則結果字串將透過省略明確的欄位名稱而更緊湊。預設情況下不轉儲諸如行號和列偏移之類的屬性。如果需要,可以將 include_attributes 設定為 true。
如果 indent 是一個非負整數或字串,則樹將以該縮排級別進行漂亮列印。縮排級別為 0、負數或
""
將僅插入換行符。None
(預設值)選擇單行表示。使用正整數縮排表示每級縮排多個空格。如果 indent 是一個字串(例如"\t"
),則該字串用於縮排每個級別。如果 show_empty 為
False
(預設值),則空列表和為None
的欄位將從輸出中省略。在 3.9 版本中更改: 添加了 indent 選項。
在 3.13 版本中更改: 添加了 show_empty 選項。
>>> print(ast.dump(ast.parse("""\ ... async def f(): ... await other_func() ... """), indent=4, show_empty=True)) Module( body=[ AsyncFunctionDef( name='f', args=arguments( posonlyargs=[], args=[], kwonlyargs=[], kw_defaults=[], defaults=[]), body=[ Expr( value=Await( value=Call( func=Name(id='other_func', ctx=Load()), args=[], keywords=[])))], decorator_list=[], type_params=[])], type_ignores=[])
編譯器標誌¶
以下標誌可以傳遞給 compile()
以更改程式編譯的效果
- ast.PyCF_ALLOW_TOP_LEVEL_AWAIT¶
啟用對頂層
await
、async for
、async with
和非同步推導式的支援。在 3.8 版本中新增。
- ast.PyCF_ONLY_AST¶
生成並返回抽象語法樹,而不是返回編譯的程式碼物件。
- ast.PyCF_OPTIMIZED_AST¶
返回的 AST 根據
compile()
或ast.parse()
中的 optimize 引數進行最佳化。3.13 版本新增。
命令列用法¶
在 3.9 版本中新增。
可以從命令列將 ast
模組作為指令碼執行。它就像
python -m ast [-m <mode>] [-a] [infile]
接受以下選項
- -h, --help¶
顯示幫助訊息並退出。
- --no-type-comments¶
不解析型別註釋。
- -a, --include-attributes¶
包含行號和列偏移等屬性。
如果指定了 infile
,則將其內容解析為 AST 並轉儲到 stdout。否則,將從 stdin 讀取內容。
另請參閱
Green Tree Snakes,一個外部文件資源,其中包含有關使用 Python AST 的詳細資訊。
ASTTokens 使用生成它們的原始碼中的標記和文字的位置來註釋 Python AST。這對於進行原始碼轉換的工具很有幫助。
leoAst.py 透過在標記和 ast 節點之間插入雙向連結,統一了 Python 程式的基於標記的檢視和基於解析樹的檢視。
LibCST 將程式碼解析為看起來像 ast 樹並保留所有格式細節的具體語法樹。它對於構建自動化重構 (codemod) 應用程式和 linters 很有用。
Parso 是一個 Python 解析器,支援錯誤恢復和不同 Python 版本(在多個 Python 版本中)的往返解析。Parso 還能夠列出 Python 檔案中的多個語法錯誤。