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)
| Interpolation(expr value, constant str, int conversion, expr? format_spec)
| JoinedStr(expr* values)
| TemplateStr(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.14 版的變更: The __repr__() output of AST nodes includes
the values of the node fields.
在 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 物件。表示的值可以是str、bytes、int、float、complex和bool的實例,以及常數None和Ellipsis。>>> 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中。
- 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.TemplateStr(values, /)¶
在 3.14 版被加入.
Node representing a template string literal, comprising a series of
InterpolationandConstantnodes. These nodes may be any order, and do not need to be interleaved.>>> expr = ast.parse('t"{name} finished {place:ordinal}"', mode='eval') >>> print(ast.dump(expr, indent=4)) Expression( body=TemplateStr( values=[ Interpolation( value=Name(id='name', ctx=Load()), str='name', conversion=-1), Constant(value=' finished '), Interpolation( value=Name(id='place', ctx=Load()), str='place', conversion=-1, format_spec=JoinedStr( values=[ Constant(value='ordinal')]))]))
- class ast.Interpolation(value, str, conversion, format_spec=None)¶
在 3.14 版被加入.
Node representing a single interpolation field in a template string literal.
value為任何運算式節點(例如文字、變數或函式呼叫)。這和FormattedValue.value的意思相同。stris a constant containing the text of the interpolation expression.conversion是一個整數:這與
FormattedValue.conversion的意思相同。format_spec是一個JoinedStr節點,表示值的格式,若未指定格式則為None。conversion和format_spec可以同時設定。這與FormattedValue.format_spec的意思相同。
- 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 annotations¶
- class ast.TypeIgnore(lineno, tag)¶
A
# type: ignorecomment located at lineno. tag is the optional tag specified by the form# type: ignore <tag>.>>> print(ast.dump(ast.parse('x = 1 # type: ignore', type_comments=True), indent=4)) Module( body=[ Assign( targets=[ Name(id='x', ctx=Store())], value=Constant(value=1))], type_ignores=[ TypeIgnore(lineno=1, tag='')]) >>> print(ast.dump(ast.parse('x: bool = 1 # type: ignore[assignment]', type_comments=True), indent=4)) Module( body=[ AnnAssign( target=Name(id='x', ctx=Store()), annotation=Name(id='bool', ctx=Load()), value=Constant(value=1), simple=1)], type_ignores=[ TypeIgnore(lineno=1, tag='[assignment]')])
備註
TypeIgnorenodes are not generated when the type_comments parameter is set toFalse(default). Seeast.parse()for more details.在 3.8 版被加入.
型別參數 (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=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 所述,其他關鍵字將被傳遞到 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、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(預設值),則輸出中將省略可選的空串列。可選的
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 版被加入.
- ast.PyCF_TYPE_COMMENTS¶
啟用對 PEP 484 和 PEP 526 樣式型別註釋的支援 (
# type: <type>,# type: ignore <stuff>)。在 3.8 版被加入.
- ast.compare(a, b, /, *, compare_attributes=False)¶
Recursively compares two ASTs.
compare_attributes affects whether AST attributes are considered in the comparison. If compare_attributes is
False(default), then attributes are ignored. Otherwise they must all be equal. This option is useful to check whether the ASTs are structurally equal but differ in whitespace or similar details. Attributes include line numbers and column offsets.在 3.14 版被加入.
命令列用法¶
在 3.9 版被加入.
ast 模組可以作為腳本從命令列執行,可以像這樣簡單地做到:
python -m ast [-m <mode>] [-a] [infile]
以下選項可被接受:
- -h, --help¶
顯示幫助訊息並退出。
- --no-type-comments¶
不要剖析型別註解。
- -a, --include-attributes¶
包括列號和行偏移量等屬性。
- --feature-version <version>¶
Python version in the format 3.x (for example, 3.10). Defaults to the current version of the interpreter.
在 3.14 版被加入.
- -O <level>¶
- --optimize <level>¶
Optimization level for parser. Defaults to no optimization.
在 3.14 版被加入.
- --show-empty¶
Show empty lists and fields that are
None. Defaults to not showing empty objects.在 3.14 版被加入.
如果指定了 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 檔案中的多個語法錯誤。