ast
--- 抽象語法樹 (Abstract Syntax Trees)¶
原始碼:Lib/ast.py
ast
模組可以幫助 Python 應用程式處理 Python 抽象語法文法 (abstract syntax grammar) 樹狀資料結構。抽象語法本身可能會隨著每個 Python 版本發布而改變;此模組有助於以程式化的方式來得知當前文法的面貌。
要生成抽象語法樹,可以透過將 ast.PyCF_ONLY_AST
作為旗標傳遞給內建函式 compile()
或使用此模組所提供的 parse()
輔助函式。結果將會是一個物件的樹,其類別都繼承自 ast.AST
。可以使用內建的 compile()
函式將抽象語法樹編譯成 Python 程式碼物件。
抽象文法 (Abstract Grammar)¶
抽象文法目前定義如下:
-- 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)
}
節點 (Node) 類別¶
- class ast.AST¶
這是所有 AST 節點類別的基礎。實際的節點類別是衍生自
Parser/Python.asdl
檔案,該檔案在上方 重現。它們被定義於_ast
的 C 模組中,並於ast
中重新匯出。抽象文法中為每個左側符號定義了一個類別(例如
ast.stmt
或ast.expr
)。此外,也為每個右側的建構函式 (constructor) 定義了一個類別;這些類別繼承自左側樹的類別。例如,ast.BinOp
繼承自ast.expr
。對於具有替代方案(即為「和 (sums)」)的生產規則,左側類別是抽象的:僅有特定建構函式節點的實例會被建立。- _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
是原始文本跨度 (source text span) 的第一個和最後一個列號(1-indexed,因此第一列號是 1)以及col_offset
和end_col_offset
是生成節點的第一個和最後一個標記對應的 UTF-8 位元組偏移量。會記錄 UTF-8 偏移量是因為剖析器 (parser) 內部使用 UTF-8。請注意,編譯器並不需要結束位置,因此其為可選的。結束偏移量在最後一個符號之後,例如可以使用
source_line[node.col_offset : node.end_col_offset]
來獲取單列運算式節點 (expression node) 的原始片段。
ast.T
類別的建構函式按以下方式剖析其引數:如果有位置引數,則必須與
T._fields
中的項目一樣多;它們將被賦値為這些名稱的屬性。如果有關鍵字引數,它們會將相同名稱的屬性設定為給定值。
例如,要建立並填充 (populate)
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 版的變更: 以它們的值表示簡單索引,擴充切片 (slice) 則以元組 (tuple) 表示。
在 3.8 版之後被棄用: 舊的類別 ast.Num
、ast.Str
、ast.Bytes
、ast.NameConstant
和 ast.Ellipsis
仍然可用,但它們將在未來的 Python 釋出版本中移除。與此同時,實例化它們將回傳不同類別的實例。
在 3.9 版之後被棄用: 舊的類別 ast.Index
和 ast.ExtSlice
仍然可用,但它們將在未來的 Python 版本中刪除。同時,實例化它們會回傳不同類別的實例。
Deprecated since version 3.13, will be removed in version 3.15: 先前版本的 Python 允許建立缺少必填欄位的 AST 節點。同樣地,AST 節點建構函式允許將任意關鍵字引數設為 AST 節點的屬性,即使它們與 AST 節點的任何欄位都不匹配。此行為已被棄用,並將在 Python 3.15 中刪除。
備註
這裡顯示的特定節點類別的描述最初是從出色的 Green Tree Snakes 專案和所有貢獻者那裡改編而來的。
根節點¶
- class ast.Module(body, type_ignores)¶
一個 Python 模組,與檔案輸入 一樣。由
ast.parse()
在預設的"exec"
mode 下生成的節點型別。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()
生成。body
是陳述式節點 (statement nodes) 的list
。>>> 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 版被加入.
文本 (Literals)¶
- class ast.Constant(value)¶
一個常數值。
Constant
文本的value
屬性包含它所代表的 Python 物件。表示的值可以是簡單型別,例如數字、字串或None
,但如果它們的所有元素都是常數,也可以是不可變的 (immutable) 容器型別(元組和凍結集合 (frozensets))。>>> print(ast.dump(ast.parse('123', mode='eval'), indent=4)) Expression( body=Constant(value=123))
- class ast.FormattedValue(value, conversion, format_spec)¶
表示 f 字串 (f-string) 中的單個格式化欄位的節點。如果字串包含單個格式欄位並且沒有其他內容,則可以隔離 (isolate) 該節點,否則它將出現在
JoinedStr
中。value
為任何運算式節點(例如文字、變數或函式呼叫)。conversion
是一個整數:-1: 無格式化
115:
!s
字串格式化114:
!r
重複格式化化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
保存表示元素的節點串列。如果容器是賦值目標(即(x,y)=something
),則ctx
是Store
,否則是Load
。>>> print(ast.dump(ast.parse('[1, 2, 3]', mode='eval'), indent=4)) Expression( body=List( elts=[ Constant(value=1), Constant(value=2), Constant(value=3)], ctx=Load())) >>> print(ast.dump(ast.parse('(1, 2, 3)', mode='eval'), indent=4)) Expression( body=Tuple( elts=[ Constant(value=1), Constant(value=2), Constant(value=3)], ctx=Load()))
- class ast.Set(elts)¶
一個集合。
elts
保存表示集合之元素的節點串列。>>> print(ast.dump(ast.parse('{1, 2, 3}', mode='eval'), indent=4)) Expression( body=Set( elts=[ Constant(value=1), Constant(value=2), Constant(value=3)]))
- class ast.Dict(keys, values)¶
一個字典 (dictionary)。
keys
和values
分別按匹配順序保存表示鍵和值的節點串列(為呼叫dictionary.keys()
和dictionary.values()
時將回傳的內容)。當使用字典文本進行字典解包 (unpack) 時,要擴充的運算式位於
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¶
變數參照可用於載入變數的值、為其分配新值或刪除它。變數參照被賦予情境 (context) 來區分這些情況。
>>> 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
保存此區段 (section) 中的一個其他節點: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)¶
一元運算 (unary operation)。
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)¶
二元運算 (binary operation)(如加法或除法)。
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¶
二元運算子 token。
- 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¶
比較運算子 token。
- 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)¶
一個附名運算式 (named expression)。該 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 版被加入.
下標 (Subscripting)¶
- 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
)。只能直接或者或者作為Tuple
的元素出現在Subscript
的 slice 欄位內。>>> 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()))
綜合運算式 (comprehensions)¶
- class ast.ListComp(elt, generators)¶
- class ast.SetComp(elt, generators)¶
- class ast.GeneratorExp(elt, generators)¶
- class ast.DictComp(key, value, generators)¶
串列和集合綜合運算、生成器運算式和字典綜合運算。
elt
(或key
和value
)是單個節點,表示各個項目會被求值 (evaluate) 的部分。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)¶
增加賦值 (augmented assignment),例如
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)¶
一個斷言 (assertion)。
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
陳述式建立的型別別名 (type alias)。name
是別名的名稱、type_params
是型別參數 (type parameter) 的串列、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 版被加入.
其他僅適用於函式或迴圈內部的陳述式將在其他部分中描述。
引入 (imports)¶
- class ast.Import(names)¶
一個 import 陳述式。
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' 名稱的原始字串,前面沒有任何的點 (dot),或者對於諸如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
包含要執行的節點串列。如果迴圈正常完成,則執行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))])])
- 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)¶
try
區塊,後面跟著except*
子句。這些屬性與Try
相同,但是handlers
中的ExceptHandler
節點被直譯 (interpret) 為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
節點(或者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()])])])
- class ast.With(items, body, type_comment)¶
一個
with
區塊。items
是表示情境管理器的withitem
節點串列,body
是情境內的縮進區塊。- type_comment¶
type_comment
是一個可選字串,其中的註解為型別註釋。
- class ast.withitem(context_expr, optional_vars)¶
with
區塊中的單個情境管理器。context_expr
是情境管理器,通常是一個Call
節點。Optional_vars
是as foo
部分的Name
、Tuple
或List
,或者如果不使用則為None
。>>> print(ast.dump(ast.parse("""\ ... with a as b, c as d: ... something(b, d) ... """), indent=4)) Module( body=[ With( items=[ withitem( context_expr=Name(id='a', ctx=Load()), optional_vars=Name(id='b', ctx=Store())), withitem( context_expr=Name(id='c', ctx=Load()), optional_vars=Name(id='d', ctx=Store()))], body=[ Expr( value=Call( func=Name(id='something', ctx=Load()), args=[ Name(id='b', ctx=Load()), Name(id='d', ctx=Load())]))])])
模式匹配 (pattern matching)¶
- class ast.Match(subject, cases)¶
一個
match
陳述式。subject
保存匹配的主題(與案例匹配的物件),cases
包含具有不同案例的match_case
節點的可疊代物件。在 3.10 版被加入.
- class ast.match_case(pattern, guard, body)¶
match
陳述式中的單個案例模式。pattern
包含主題將與之匹配的匹配模式。請注意,為模式生成的AST
節點與為運算式生成的節點不同,即使它們共享相同的語法。guard
屬性包含一個運算式,如果模式與主題匹配,則將對該運算式求值。body
包含一個節點串列,如果模式匹配並且為防護運算式 (guard expression) 的求值 (evaluate) 結果為真,則會執行該節點串列。>>> 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
是一個運算式節點。允許值節點受到匹配陳述式文件中所述的限制。如果匹配主題等於求出值,則此模式成功。>>> 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)¶
按識別性 (identity) 進行比較的匹配文本模式。
value
是要與None
、True
或False
進行比較的單例 (singleton)。如果匹配主題是給定的常數,則此模式成功。>>> 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
是一個給定要匹配的名義類別 (nominal class) 的運算式。patterns
是要與類別定義的模式匹配屬性序列進行匹配的模式節點序列。kwd_attrs
是要匹配的附加屬性序列(在類別模式中指定為關鍵字引數),kwd_patterns
是相應的模式(在類別模式中指定為關鍵字的值)。如果主題是指定類別的實例,所有位置模式都與相應的類別定義屬性匹配,並且任何指定的關鍵字屬性與其相應模式匹配,則此模式成功。
注意:類別可以定義一個回傳 self 的特性 (property),以便將模式節點與正在匹配的實例進行匹配。一些內建型別也以這種方式匹配,如同匹配陳述式文件中所述。
>>> 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 模式 (as-pattern)」,為捕獲模式 (capture pattern) 或通配模式 (wildcard pattern)。
pattern
包含主題將與之匹配的匹配模式。如果模式為None
,則該節點代表捕獲模式(即裸名 (bare name))並且始終會成功。name
屬性包含模式成功時將綁定的名稱。如果name
為None
,則pattern
也必須為None
,並且節點代表通配模式。>>> print(ast.dump(ast.parse(""" ... match x: ... case [x] as y: ... ... ... case _: ... ... ... """), indent=4)) Module( body=[ Match( subject=Name(id='x', ctx=Load()), cases=[ match_case( pattern=MatchAs( pattern=MatchSequence( patterns=[ MatchAs(name='x')]), name='y'), body=[ Expr( value=Constant(value=Ellipsis))]), match_case( pattern=MatchAs(), body=[ Expr( value=Constant(value=Ellipsis))])])])
在 3.10 版被加入.
- class ast.MatchOr(patterns)¶
匹配的 「or 模式 (or-pattern)」。 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))])])])
在 3.10 版被加入.
型別參數 (type parameters)¶
型別參數可以存在於類別、函式和型別別名上。
- class ast.TypeVar(name, bound, default_value)¶
一個
typing.TypeVar
。name
是型別變數的名稱。bound
是(如果有存在的)界限 (bound) 或約束 (constraint)。如果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=Tuple( 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 所述,其他關鍵字將被傳遞到 metaclass。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
主體 (body) 中有效。
>>> 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
、:class: ast.boolop
和 ast.expr_context
)將是單例。對其中之一的更改將反映在所有其他出現的相同值中(例如 ast.Add
)。
ast
輔助程式¶
除了節點類別之外,ast
模組還定義了這些用於遍歷 (traverse) 抽象語法樹的實用函式和類別:
- 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「簽名型別註解 (signature type comments)」而被修改,例如(str, int) -> List[str]
。將
feature_version
設定為元組(major, minor)
將「盡可能」嘗試使用該 Python 版本的文法進行剖析。當前major
必須等於3
。例如,設定feature_version=(3, 9)
將嘗試禁止剖析match
陳述式。目前major
必須為3
、支援的最低版本為(3, 7)
(這在未來的 Python 版本中可能會增加);最高的是sys.version_info[0:2]
。「盡可能」嘗試意味著不能保證剖析(或剖析的成功)與在與feature_version
對應的 Python 版本上運行時相同。如果來源包含 null 字元 (
\0
),則會引發ValueError
。警告
請注意,成功將原始碼剖析為 AST 物件並不能保證提供的原始碼是可以執行的有效 Python 程式碼,因為編譯步驟可能會引發進一步的
SyntaxError
例外。例如,原始的return 42
為 return 陳述式生成一個有效的 AST 節點,但它不能單獨編譯(它需要位於函式節點內)。特別是
ast.parse()
不會執行任何範圍檢查,而編譯步驟才會執行此操作。警告
由於 Python AST 編譯器中的堆疊 (stack) 深度限制,太大或太複雜的字串可能會導致 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 版的變更: 現在允許位元組和集合文本 (set literal)。
在 3.9 版的變更: 現在支援使用
'set()'
建立空集合。在 3.10 版的變更: 對於字串輸入,前導空格和定位字元 (tab) 現在已被去除。
- ast.get_docstring(node, clean=True)¶
回傳給定 node 的文件字串 (docstring)(必須是
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
,則多列陳述式的第一列將用空格填充 (padded) 以匹配其原始位置。在 3.8 版被加入.
- ast.fix_missing_locations(node)¶
當你使用
compile()
編譯節點樹時,對於每個有支援lineno
和col_offset
屬性之節點,編譯器預期他們的這些屬性都要存在。填入生成的節點相當繁瑣,因此該輔助工具透過將這些屬性設定為父節點的值,在尚未設定的地方遞迴地新增這些屬性。它從 node 開始遞迴地作用。
- ast.increment_lineno(node, n=1)¶
將樹中從 node 開始的每個節點的列號和結束列號增加 n。這對於「移動程式碼」到檔案中的不同位置很有用。
- ast.copy_location(new_node, old_node)¶
如果可行,將原始位置(
lineno
、col_offset
、end_lineno
和end_col_offset
)從 old_node 複製到 new_node,並回傳 new_node 。
- ast.iter_fields(node)¶
為 node 上存在的
node._fields
中的每個欄位生成一個(fieldname, value)
元組。
- ast.iter_child_nodes(node)¶
生成 node 的所有直接子節點,即作為節點的所有欄位以及作為節點串列欄位的所有項目。
- ast.walk(node)¶
遞迴地生成樹中從 node 開始的所有後代節點(包括 node 本身),不按指定順序。如果你只想就地修改節點而不關心情境,這非常有用。
- class ast.NodeVisitor¶
節點訪問者基底類別,它遍歷抽象語法樹並為找到的每個節點呼叫訪問者函式。該函式可能會回傳一個由
visit()
方法轉發的值。這個類別應該被子類別化,子類別新增訪問者方法。
- visit(node)¶
訪問一個節點。預設實作呼叫名為
self.visit_classname
的方法,其中 classname 是節點類別的名稱,或者在該方法不存在時呼叫generic_visit()
。
- generic_visit(node)¶
該訪問者對該節點的所有子節點呼叫
visit()
。請注意,除非訪問者呼叫
generic_visit()
或訪問它們本身,否則不會訪問具有自定義訪問者方法的節點之子節點。
- visit_Constant(node)¶
處理所有常數節點。
如果你想在遍歷期間將變更應用 (apply) 於節點,請不要使用
NodeVisitor
。為此,有個允許修改的特殊遍歷訪問者工具NodeTransformer
。在 3.8 版之後被棄用:
visit_Num()
、visit_Str()
、visit_Bytes()
、visit_NameConstant()
和visit_Ellipsis()
方法現已棄用,並且不會在未來的Python 版本中被呼叫。新增visit_Constant()
方法來處理所有常數節點。
- class ast.NodeTransformer¶
一個
NodeVisitor
子類別,它會遍歷抽象語法樹並允許修改節點。NodeTransformer
將遍歷 AST 並使用訪問者方法的回傳值來替換或刪除舊節點。如果訪問者方法的回傳值為None
,則該節點將從其位置中刪除,否則將被替換為回傳值。回傳值可能是原始節點,在這種情況下不會發生替換。下面是一個示範用的 transformer,它將查找所有出現名稱 (
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()
方法。對於屬於陳述式總集 (collection) 一部分的節點(適用於所有陳述式節點),訪問者還可以回傳節點串列,而不僅僅是單個節點。
如果
NodeTransformer
引進了新節點(不屬於原始樹的一部分),但沒有給它們提供位置資訊(例如lineno
),則應使用新的子樹呼叫fix_missing_locations()
以重新計算位置資訊:tree = ast.parse('foo', mode='eval') new_tree = fix_missing_locations(RewriteName().visit(tree))
你通常會像這樣使用 transformer:
node = YourTransformer().visit(node)
- ast.dump(node, annotate_fields=True, include_attributes=False, *, indent=None, show_empty=False)¶
回傳 node 中樹的格式化傾印 (formatted dump),這主要用於除錯。如果 annotate_fields 為 true(為預設值),則回傳的字串將顯示欄位的名稱和值。如果 annotate_fields 為 false,則透過省略明確的欄位名稱,結果字串將更加縮減簡潔。預設情況下,不會傾印列號和行偏移量等屬性。如果需要,可以設定 include_attributes 為 true。
如果 indent 是非負整數或字串,那麼樹將使用該縮排級別來做漂亮印出 (pretty-print)。縮排級別 0、負數或
""
只會插入換列符號 (newlines)。None
(預設值)代表選擇單列表示。使用正整數縮排可以在每個級別縮排相同數量的空格。如果 indent 是一個字串(例如"\t"
),則該字串用於縮排每個級別。如果 show_empty 為
False
(預設值),則輸出中將省略False
的空串列和欄位。在 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 並傾印 (dump) 到 stdout。否則會從 stdin 讀取內容。
也參考
Green Tree Snakes 是一個外部文件資源,提供了有關使用 Python AST 的詳細資訊。
ASTTokens 使用生成它們的原始碼中的標記和文本的位置來註釋 Python AST。這對於進行原始碼轉換的工具很有幫助。
leoAst.py 透過在 token 和 ast 節點之間插入雙向鏈結,統一了 python 程式的基於 token 和基於剖析樹的視圖。
LibCST 將程式碼剖析為具體語法樹 (Concrete Syntax Tree),看起來像 ast 樹並保留所有格式詳細資訊。它對於建置自動重構 (codemod) 應用程式和 linter 非常有用。
Parso 是一個 Python 剖析器,支援不同 Python 版本的錯誤復原和往返剖析。Parso 還能夠列出 Python 檔案中的多個語法錯誤。