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, constantmodulePython{mod=Module(stmt*body,type_ignore*type_ignores)|Interactive(stmt*body)|Expression(exprbody)|FunctionType(expr*argtypes,exprreturns)stmt=FunctionDef(identifiername,argumentsargs,stmt*body,expr*decorator_list,expr?returns,string?type_comment,type_param*type_params)|AsyncFunctionDef(identifiername,argumentsargs,stmt*body,expr*decorator_list,expr?returns,string?type_comment,type_param*type_params)|ClassDef(identifiername,expr*bases,keyword*keywords,stmt*body,expr*decorator_list,type_param*type_params)|Return(expr?value)|Delete(expr*targets)|Assign(expr*targets,exprvalue,string?type_comment)|TypeAlias(exprname,type_param*type_params,exprvalue)|AugAssign(exprtarget,operatorop,exprvalue)-- 'simple' indicates that we annotate simple name without parens|AnnAssign(exprtarget,exprannotation,expr?value,intsimple)-- use 'orelse' because else is a keyword in target languages|For(exprtarget,expriter,stmt*body,stmt*orelse,string?type_comment)|AsyncFor(exprtarget,expriter,stmt*body,stmt*orelse,string?type_comment)|While(exprtest,stmt*body,stmt*orelse)|If(exprtest,stmt*body,stmt*orelse)|With(withitem*items,stmt*body,string?type_comment)|AsyncWith(withitem*items,stmt*body,string?type_comment)|Match(exprsubject,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(exprtest,expr?msg)|Import(alias*names)|ImportFrom(identifier?module,alias*names,int?level)|Global(identifier*names)|Nonlocal(identifier*names)|Expr(exprvalue)|Pass|Break|Continue-- col_offset is the byte offset in the utf8 string the parser usesattributes(intlineno,intcol_offset,int?end_lineno,int?end_col_offset)-- BoolOp() can use left & right?expr=BoolOp(boolopop,expr*values)|NamedExpr(exprtarget,exprvalue)|BinOp(exprleft,operatorop,exprright)|UnaryOp(unaryopop,exproperand)|Lambda(argumentsargs,exprbody)|IfExp(exprtest,exprbody,exprorelse)|Dict(expr*keys,expr*values)|Set(expr*elts)|ListComp(exprelt,comprehension*generators)|SetComp(exprelt,comprehension*generators)|DictComp(exprkey,exprvalue,comprehension*generators)|GeneratorExp(exprelt,comprehension*generators)-- the grammar constrains where yield expressions can occur|Await(exprvalue)|Yield(expr?value)|YieldFrom(exprvalue)-- need sequences for compare to distinguish between-- x < 4 < 3 and (x < 4) < 3|Compare(exprleft,cmpop*ops,expr*comparators)|Call(exprfunc,expr*args,keyword*keywords)|FormattedValue(exprvalue,intconversion,expr?format_spec)|JoinedStr(expr*values)|Constant(constantvalue,string?kind)-- the following expression can appear in assignment context|Attribute(exprvalue,identifierattr,expr_contextctx)|Subscript(exprvalue,exprslice,expr_contextctx)|Starred(exprvalue,expr_contextctx)|Name(identifierid,expr_contextctx)|List(expr*elts,expr_contextctx)|Tuple(expr*elts,expr_contextctx)-- can appear only in Subscript|Slice(expr?lower,expr?upper,expr?step)-- col_offset is the byte offset in the utf8 string the parser usesattributes(intlineno,intcol_offset,int?end_lineno,int?end_col_offset)expr_context=Load|Store|Delboolop=And|Oroperator=Add|Sub|Mult|MatMult|Div|Mod|Pow|LShift|RShift|BitOr|BitXor|BitAnd|FloorDivunaryop=Invert|Not|UAdd|USubcmpop=Eq|NotEq|Lt|LtE|Gt|GtE|Is|IsNot|In|NotIncomprehension=(exprtarget,expriter,expr*ifs,intis_async)excepthandler=ExceptHandler(expr?type,identifier?name,stmt*body)attributes(intlineno,intcol_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=(identifierarg,expr?annotation,string?type_comment)attributes(intlineno,intcol_offset,int?end_lineno,int?end_col_offset)-- keyword arguments supplied to call (NULL identifier for **kwargs)keyword=(identifier?arg,exprvalue)attributes(intlineno,intcol_offset,int?end_lineno,int?end_col_offset)-- import name with optional 'as' alias.alias=(identifiername,identifier?asname)attributes(intlineno,intcol_offset,int?end_lineno,int?end_col_offset)withitem=(exprcontext_expr,expr?optional_vars)match_case=(patternpattern,expr?guard,stmt*body)pattern=MatchValue(exprvalue)|MatchSingleton(constantvalue)|MatchSequence(pattern*patterns)|MatchMapping(expr*keys,pattern*patterns,identifier?rest)|MatchClass(exprcls,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(intlineno,intcol_offset,intend_lineno,intend_col_offset)type_ignore=TypeIgnore(intlineno,stringtag)type_param=TypeVar(identifiername,expr?bound,expr?default_value)|ParamSpec(identifiername,expr?default_value)|TypeVarTuple(identifiername,expr?default_value)attributes(intlineno,intcol_offset,intend_lineno,intend_col_offset)}

節點 (Node) 類別

classast.AST

這是所有 AST 節點類別的基礎。實際的節點類別是衍生自Parser/Python.asdl 檔案,該檔案在上方 重現。它們被定義於_ast 的 C 模組中,並於ast 中重新匯出。

抽象文法中為每個左側符號定義了一個類別(例如ast.stmtast.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.exprast.stmt 子類別的實例具有linenocol_offsetend_linenoend_col_offset 屬性。linenoend_lineno 是原始文本跨度 (source text span) 的第一個和最後一個列號(1-indexed,因此第一列號是 1)以及col_offsetend_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.Numast.Strast.Bytesast.NameConstantast.Ellipsis 仍然可用,但它們將在未來的 Python 釋出版本中移除。與此同時,實例化它們將回傳不同類別的實例。

在 3.9 版之後被棄用:舊的類別ast.Indexast.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 專案和所有貢獻者那裡改編而來的。

根節點

classast.Module(body,type_ignores)

一個 Python 模組,與檔案輸入 一樣。由ast.parse() 在預設的"exec"mode 下生成的節點型別。

body 是模組的陳述式 的一個list

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))])
classast.Expression(body)

單個 Python運算式輸入。當mode"eval" 時節點型別由ast.parse() 生成。

body 是單個節點,是運算式型別的其中之一。

>>>print(ast.dump(ast.parse('123',mode='eval'),indent=4))Expression(    body=Constant(value=123))
classast.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))])
classast.FunctionType(argtypes,returns)

函式的舊式型別註解的表示法,因為 3.5 之前的 Python 版本不支援PEP 484 註釋。當mode"func_type" 時節點型別由ast.parse() 生成。

這種型別的註解看起來像這樣:

defsum_two_number(a,b):# type: (int, int) -> intreturna+b

argtypes運算式節點list

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)

classast.Constant(value)

一個常數值。Constant 文本的value 屬性包含它所代表的 Python 物件。表示的值可以是簡單型別,例如數字、字串或None,但如果它們的所有元素都是常數,也可以是不可變的 (immutable) 容器型別(元組和凍結集合 (frozensets))。

>>>print(ast.dump(ast.parse('123',mode='eval'),indent=4))Expression(    body=Constant(value=123))
classast.FormattedValue(value,conversion,format_spec)

表示 f 字串 (f-string) 中的單個格式化欄位的節點。如果字串包含單個格式欄位並且沒有其他內容,則可以隔離 (isolate) 該節點,否則它將出現在JoinedStr 中。

  • value 為任何運算式節點(例如文字、變數或函式呼叫)。

  • conversion 是一個整數:

    • -1: 無格式化

    • 115:!s 字串格式化

    • 114:!r 重複格式化化

    • 97:!a ascii 格式化

  • format_spec 是一個JoinedStr 節點,表示值的格式,若未指定格式則為Noneconversionformat_spec 可以同時設定。

classast.JoinedStr(values)

一個 f 字串,包含一系列FormattedValueConstant 節點。

>>>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')]))]))
classast.List(elts,ctx)
classast.Tuple(elts,ctx)

串列或元組。elts 保存表示元素的節點串列。如果容器是賦值目標(即(x,y)=something ),則ctxStore,否則是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()))
classast.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)]))
classast.Dict(keys,values)

一個字典 (dictionary)。keysvalues 分別按匹配順序保存表示鍵和值的節點串列(為呼叫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())]))

變數

classast.Name(id,ctx)

一個變數名稱。id 將名稱以字串形式保存,且ctx 是以下型別之一。

classast.Load
classast.Store
classast.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())])])
classast.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()))])

運算式

classast.Expr(value)

當運算式(例如函式呼叫)本身作為陳述式出現且未使用或儲存其回傳值時,它將被包裝在此容器中。value 保存此區段 (section) 中的一個其他節點:ConstantNameLambdaYieldYieldFrom

>>>print(ast.dump(ast.parse('-a'),indent=4))Module(    body=[        Expr(            value=UnaryOp(                op=USub(),                operand=Name(id='a', ctx=Load())))])
classast.UnaryOp(op,operand)

一元運算 (unary operation)。op 是運算子,operand 是任何運算式節點。

classast.UAdd
classast.USub
classast.Not
classast.Invert

一元運算子標記。Notnot 關鍵字、Invert~ 運算子。

>>>print(ast.dump(ast.parse('not x',mode='eval'),indent=4))Expression(    body=UnaryOp(        op=Not(),        operand=Name(id='x', ctx=Load())))
classast.BinOp(left,op,right)

二元運算 (binary operation)(如加法或除法)。op 是運算子、leftright 是任意運算式節點。

>>>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())))
classast.Add
classast.Sub
classast.Mult
classast.Div
classast.FloorDiv
classast.Mod
classast.Pow
classast.LShift
classast.RShift
classast.BitOr
classast.BitXor
classast.BitAnd
classast.MatMult

二元運算子 token。

classast.BoolOp(op,values)

布林運算 'or' 或 'and'。opOrAndvalues 是有所涉及的值。使用同一運算子的連續操作(例如aorborc)會被折疊為具有多個值的一個節點。

這不包括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())]))
classast.And
classast.Or

布林運算子 token。

classast.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)]))
classast.Eq
classast.NotEq
classast.Lt
classast.LtE
classast.Gt
classast.GtE
classast.Is
classast.IsNot
classast.In
classast.NotIn

比較運算子 token。

classast.Call(func,args,keywords)

一個函式呼叫。func 是該函式,通常是一個NameAttribute 物件。而在引數中:

  • args 保存按位置傳遞的引數串列。

  • keywords 保存一個keyword 物件串列,表示透過關鍵字傳遞的引數。

argskeywords 引數是可選的,預設為空串列。

>>>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()))]))
classast.keyword(arg,value)

函式呼叫或類別定義的關鍵字引數。arg 是參數名稱的原始字串,value 是要傳入的節點。

classast.IfExp(test,body,orelse)

像是aifbelsec 之類的運算式。每個欄位都保存一個節點,因此在以下範例中,所有三個都是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())))
classast.Attribute(value,attr,ctx)

屬性的存取,例如d.keysvalue 是一個節點,通常是一個Nameattr 是一個屬性名稱的字串,ctx 根據屬性的作用方式可能是LoadStoreDel

>>>print(ast.dump(ast.parse('snake.colour',mode='eval'),indent=4))Expression(    body=Attribute(        value=Name(id='snake', ctx=Load()),        attr='colour',        ctx=Load()))
classast.NamedExpr(target,value)

一個附名運算式 (named expression)。該 AST 節點由賦值運算式運算子(也稱為海象運算子)產生。相對於Assign 節點之第一個引數可為多個節點,在這種情況下targetvalue 都必須是單個節點。

>>>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)

classast.Subscript(value,slice,ctx)

一個下標,例如l[1]value 是下標物件(通常是序列或對映)。slice 是索引、切片或鍵。它可以是一個Tuple 並包含一個Slice。根據下標執行的操作不同,ctx 可以是LoadStoreDel

>>>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()))
classast.Slice(lower,upper,step)

常規切片(形式為lower:upperlower:upper:step)。只能直接或者或者作為Tuple 的元素出現在Subscriptslice 欄位內。

>>>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)

classast.ListComp(elt,generators)
classast.SetComp(elt,generators)
classast.GeneratorExp(elt,generators)
classast.DictComp(key,value,generators)

串列和集合綜合運算、生成器運算式和字典綜合運算。elt(或keyvalue)是單個節點,表示各個項目會被求值 (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)]))
classast.comprehension(target,iter,ifs,is_async)

綜合運算中的一個for 子句。target 是用於每個元素的參照 - 通常是NameTuple 節點。iter 是要疊代的物件。ifs 是測試運算式的串列:每個for 子句可以有多個ifs

is_async 表示綜合運算式是非同步的(使用asyncfor 而不是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 comprehensionExpression(    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 comprehensionExpression(    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)]))

陳述式

classast.Assign(targets,value,type_comment)

一個賦值。targets 是節點串列,value 是單個節點。

targets 中的多個節點表示為每個節點分配相同的值。解包是透過在targets 中放置一個TupleList 來表示的。

type_comment

type_comment 是一個可選字串,其中的註解為型別註釋。

>>>print(ast.dump(ast.parse('a = b = 1'),indent=4))# Multiple assignmentModule(    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))# UnpackingModule(    body=[        Assign(            targets=[                Tuple(                    elts=[                        Name(id='a', ctx=Store()),                        Name(id='b', ctx=Store())],                    ctx=Store())],            value=Name(id='c', ctx=Load()))])
classast.AnnAssign(target,annotation,value,simple)

帶有型別註釋的賦值。target 是單個節點,可以是NameAttributeSubscriptannotation 是註釋,例如ConstantName 節點。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 parenthesisModule(    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 annotationModule(    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 annotationModule(    body=[        AnnAssign(            target=Subscript(                value=Name(id='a', ctx=Load()),                slice=Constant(value=1),                ctx=Store()),            annotation=Name(id='int', ctx=Load()),            simple=0)])
classast.AugAssign(target,op,value)

增加賦值 (augmented assignment),例如a+=1。在下面的範例中,targetxName 節點(帶有Store 情境),opAddvalue 是一個值為 1 的Constant

Assign 的目標不同,target 屬性不能屬於TupleList 類別。

>>>print(ast.dump(ast.parse('x += 2'),indent=4))Module(    body=[        AugAssign(            target=Name(id='x', ctx=Store()),            op=Add(),            value=Constant(value=2))])
classast.Raise(exc,cause)

一個raise 陳述式。exc 是要引發的例外物件,通常是CallName,若是獨立的raise 則為Nonecauseraisexfromy 中的可選部分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()))])
classast.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()))])
classast.Delete(targets)

代表一個del 陳述式。targets 是節點串列,例如NameAttributeSubscript 節點。

>>>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())])])
classast.Pass

一個pass 陳述式。

>>>print(ast.dump(ast.parse('pass'),indent=4))Module(    body=[        Pass()])
classast.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)

classast.Import(names)

一個 import 陳述式。namesalias 節點的串列。

>>>print(ast.dump(ast.parse('import x,y,z'),indent=4))Module(    body=[        Import(            names=[                alias(name='x'),                alias(name='y'),                alias(name='z')])])
classast.ImportFrom(module,names,level)

代表fromximportymodule 是 'from' 名稱的原始字串,前面沒有任何的點 (dot),或者對於諸如from.importfoo 之類的陳述式則為Nonelevel 是一個整數,保存相對引入的級別(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)])
classast.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 之類的可選子句如果不存在,則將被儲存為空串列。

classast.If(test,body,orelse)

一個if 陳述式。test 保存單個節點,例如Compare 節點。bodyorelse 各自保存一個節點串列。

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))])])])
classast.For(target,iter,body,orelse,type_comment)

一個for 迴圈。target 保存迴圈賦予的變數,為單個NameTupleListAttributeSubscript 節點。iter 保存要迴圈跑過的項目,也為單個節點。bodyorelse 包含要執行的節點串列。如果迴圈正常完成,則執行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))])])
classast.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))])])
classast.Break
classast.Continue

breakcontinue 陳述式。

>>>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()])])])
classast.Try(body,handlers,orelse,finalbody)

try 區塊。除handlersExceptHandler 節點的串列外,其他所有屬性都是要執行之節點的串列。

>>>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))])])
classast.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 版被加入.

classast.ExceptHandler(type,name,body)

單個except 子句。type 是會被匹配的例外型別,通常是一個Name 節點(或者None 表示會捕捉到所有例外的except: 子句)。name 是用於保存例外的名稱之原始字串,如果子句沒有asfoo ,則為Nonebody 是節點串列。

>>>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()])])])
classast.With(items,body,type_comment)

一個with 區塊。items 是表示情境管理器的withitem 節點串列,body 是情境內的縮進區塊。

type_comment

type_comment 是一個可選字串,其中的註解為型別註釋。

classast.withitem(context_expr,optional_vars)

with 區塊中的單個情境管理器。context_expr 是情境管理器,通常是一個Call 節點。Optional_varsasfoo 部分的NameTupleList,或者如果不使用則為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)

classast.Match(subject,cases)

一個match 陳述式。subject 保存匹配的主題(與案例匹配的物件),cases 包含具有不同案例的match_case 節點的可疊代物件。

在 3.10 版被加入.

classast.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 版被加入.

classast.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 版被加入.

classast.MatchSingleton(value)

按識別性 (identity) 進行比較的匹配文本模式。value 是要與NoneTrueFalse 進行比較的單例 (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 版被加入.

classast.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 版被加入.

classast.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 版被加入.

classast.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 版被加入.

classast.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 版被加入.

classast.MatchAs(pattern,name)

匹配的 「as 模式 (as-pattern)」,為捕獲模式 (capture pattern) 或通配模式 (wildcard pattern)。pattern 包含主題將與之匹配的匹配模式。如果模式為None,則該節點代表捕獲模式(即裸名 (bare name))並且始終會成功。

name 屬性包含模式成功時將綁定的名稱。如果nameNone,則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 版被加入.

classast.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

classast.TypeIgnore(lineno,tag)

A#type:ignore comment located atlineno.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]')])

備註

TypeIgnore nodes are not generated when thetype_comments parameteris set toFalse (default). Seeast.parse() for more details.

在 3.8 版被加入.

型別參數 (type parameters)

型別參數可以存在於類別、函式和型別別名上。

classast.TypeVar(name,bound,default_value)

一個typing.TypeVarname 是型別變數的名稱。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 參數。

classast.ParamSpec(name,default_value)

一個typing.ParamSpecname 是參數規範的名稱。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 參數。

classast.TypeVarTuple(name,default_value)

一個typing.TypeVarTuplename 是型別變數元組的名稱。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 參數。

函式和類別定義

classast.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

classast.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)))])
classast.arguments(posonlyargs,args,vararg,kwonlyargs,kw_defaults,kwarg,defaults)

函式的引數。

  • posonlyargsargskwonlyargsarg 節點的串列。

  • varargkwarg 是單個arg 節點,指的是*args,**kwargs 參數。

  • kw_defaults 是僅限關鍵字引數的預設值串列。如果其中某個為None,則相應參數就會是必要的。

  • defaults 是可以按位置傳遞的引數的預設值串列。如果預設值較少,則它們對應於最後 n 個引數。

classast.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'))])
classast.Return(value)

一個return 陳述式。

>>>print(ast.dump(ast.parse('return 4'),indent=4))Module(    body=[        Return(            value=Constant(value=4))])
classast.Yield(value)
classast.YieldFrom(value)

一個yieldyieldfrom 運算式。因為這些是運算式,所以如果不使用發送回來的值,則必須將它們包裝在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())))])
classast.Global(names)
classast.Nonlocal(names)

globalnonlocal 陳述式。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'])])
classast.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

classast.AsyncFunctionDef(name,args,body,decorator_list,returns,type_comment,type_params)

一個asyncdef 函式定義。與FunctionDef 具有相同的欄位。

在 3.12 版的變更:新增了type_params

classast.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()))))])])
classast.AsyncFor(target,iter,body,orelse,type_comment)
classast.AsyncWith(items,body,type_comment)

asyncfor 迴圈和asyncwith 情境管理器。它們分別具有與ForWith 相同的欄位。僅在AsyncFunctionDef 主體中有效。

備註

當字串被ast.parse() 剖析時,回傳樹的運算子節點(ast.operatorast.unaryopast.cmpop、:class:ast.boolopast.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_VALUEoptimize<=0 時為ast.PyCF_ONLY_AST,否則為ast.PyCF_OPTIMIZED_AST

如果給定type_comments=True,剖析器將被修改為檢查並回傳PEP 484PEP 526 指定的型別註釋。這相當於將ast.PyCF_TYPE_COMMENTS 新增到傳遞給compile() 的旗標中。這將報告錯誤型別註釋的語法錯誤。如果沒有此旗標,型別註釋將被忽略,並且所選 AST 節點上的type_comment 欄位將始終為None。此外,#type:ignore 註釋的位置將作為Moduletype_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 例外。例如,原始的return42 為 return 陳述式生成一個有效的 AST 節點,但它不能單獨編譯(它需要位於函式節點內)。

特別是ast.parse() 不會執行任何範圍檢查,而編譯步驟才會執行此操作。

警告

由於 Python AST 編譯器中的堆疊 (stack) 深度限制,太大或太複雜的字串可能會導致 Python 直譯器崩潰。

在 3.8 版的變更:新增type_commentsmode='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 文本結構:字串、位元組、數字、元組、串列、字典、集合、布林值、NoneEllipsis

這可用於為包含 Python 值的字串求值,而無需自己剖析這些值。它無法計算任意複雜的運算式,例如涉及運算子或索引。

該函式過去被記錄為「安全」,但沒有定義其含義,這有點誤導讀者,它是特別設計為不去執行 Python 程式碼,與更通用的eval() 不同。沒有命名空間、沒有名稱查找、也沒有呼叫的能力。但它也不能免受攻擊:相對較小的輸入可能會導致記憶體耗盡或 C 堆疊耗盡,從而導致行程崩潰。某些輸入也可能會出現 CPU 消耗過多而導致拒絕服務的情況。因此不建議在不受信任的資料上呼叫它。

警告

由於 Python AST 編譯器的堆疊深度限制,Python 直譯器可能會崩潰。

它可能會引發ValueErrorTypeErrorSyntaxErrorMemoryErrorRecursionError,具體取決於格式錯誤的輸入。

在 3.2 版的變更:現在允許位元組和集合文本 (set literal)。

在 3.9 版的變更:現在支援使用'set()' 建立空集合。

在 3.10 版的變更:對於字串輸入,前導空格和定位字元 (tab) 現在已被去除。

ast.get_docstring(node,clean=True)

回傳給定node 的文件字串 (docstring)(必須是FunctionDefAsyncFunctionDefClassDefModule 節點)或如果它沒有文件字串則為None。如果clean 為 true,則使用inspect.cleandoc() 清理文件字串的縮排。

在 3.5 版的變更:目前已支援AsyncFunctionDef

ast.get_source_segment(source,node,*,padded=False)

取得生成nodesource 的原始碼片段。如果某些位置資訊(linenoend_linenocol_offsetend_col_offset)遺漏,則回傳None

如果paddedTrue,則多列陳述式的第一列將用空格填充 (padded) 以匹配其原始位置。

在 3.8 版被加入.

ast.fix_missing_locations(node)

當你使用compile() 編譯節點樹時,對於每個有支援linenocol_offset 屬性之節點,編譯器預期他們的這些屬性都要存在。填入生成的節點相當繁瑣,因此該輔助工具透過將這些屬性設定為父節點的值,在尚未設定的地方遞迴地新增這些屬性。它從node 開始遞迴地作用。

ast.increment_lineno(node,n=1)

將樹中從node 開始的每個節點的列號和結束列號增加n。這對於「移動程式碼」到檔案中的不同位置很有用。

ast.copy_location(new_node,old_node)

如果可行,將原始位置(linenocol_offsetend_linenoend_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 本身),不按指定順序。如果你只想就地修改節點而不關心情境,這非常有用。

classast.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() 方法來處理所有常數節點。

classast.NodeTransformer

一個NodeVisitor 子類別,它會遍歷抽象語法樹並允許修改節點。

NodeTransformer 將遍歷 AST 並使用瀏覽者方法的回傳值來替換或刪除舊節點。如果瀏覽者方法的回傳值為None,則該節點將從其位置中刪除,否則將被替換為回傳值。回傳值可能是原始節點,在這種情況下不會發生替換。

下面是一個示範用的 transformer,它將查找所有出現名稱 (foo) 並改寫為data['foo']

classRewriteName(NodeTransformer):defvisit_Name(self,node):returnSubscript(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_emptyFalse (預設值),則輸出中將省略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

啟用對最高階awaitasyncforasyncwith 和非同步綜合運算的支援。

在 3.8 版被加入.

ast.PyCF_ONLY_AST

生成並回傳抽象語法樹,而不是回傳已編譯的程式碼物件。

ast.PyCF_OPTIMIZED_AST

回傳的 AST 會根據compile()ast.parse() 中的optimize 引數進行最佳化。

在 3.13 版被加入.

ast.PyCF_TYPE_COMMENTS

啟用對PEP 484PEP 526 樣式型別註釋的支援 (#type:<type>,#type:ignore<stuff>)。

在 3.8 版被加入.

命令列用法

在 3.9 版被加入.

ast 模組可以作為腳本從命令列執行,可以像這樣簡單地做到:

python-mast[-m<mode>][-a][infile]

以下選項可被接受:

-h,--help

顯示幫助訊息並退出。

-m<mode>
--mode<mode>

指定必須編譯哪種類型的程式碼,像是parse() 中的mode 引數。

--no-type-comments

不要剖析型別註解。

-a,--include-attributes

包括列號和行偏移量等屬性。

-i<indent>
--indent<indent>

AST 中節點的縮進(空格數)。

如果指定了infile,則其內容將被剖析為 AST 並傾印 (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 檔案中的多個語法錯誤。