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.stmt
或ast.expr
)。此外,也為每個右側的建構函式 (constructor) 定義了一個類別;這些類別繼承自左側樹的類別。例如,ast.BinOp
繼承自ast.expr
。對於具有替代方案(即為「和 (sums)」)的生產規則,左側類別是抽象的:僅有特定建構函式節點的實例會被建立。- _fields¶
每個具體類別都有一個屬性
_fields
,它會給出所有子節點的名稱。具體類別的每個實例對於每個子節點都有一個屬性,其型別如文法中所定義。例如,
ast.BinOp
實例具有型別為ast.expr
的屬性left
。如果這些屬性在文法中被標記為可選(使用問號),則該值可能為
None
。如果屬性可以有零個或多個值(用星號標記),則這些值將表示為 Python 串列。使用compile()
編譯 AST 時,所有可能的屬性都必須存在並且具有有效值。
- _field_types¶
每個具體類別上的
_field_types
屬性是將欄位名稱(也在_fields
中列出)對映到其型別的字典。>>>ast.TypeVar._field_types{'name': <class 'str'>, 'bound': ast.expr | None, 'default_value': ast.expr | None}
在 3.13 版被加入.
- lineno¶
- col_offset¶
- end_lineno¶
- end_col_offset¶
ast.expr
和ast.stmt
子類別的實例具有lineno
、col_offset
、end_lineno
和end_col_offset
屬性。lineno
和end_lineno
是原始文本跨度 (source text span) 的第一個和最後一個列號(1-indexed,因此第一列號是 1)以及col_offset
和end_col_offset
是生成節點的第一個和最後一個標記對應的 UTF-8 位元組偏移量。會記錄 UTF-8 偏移量是因為剖析器 (parser) 內部使用 UTF-8。請注意,編譯器並不需要結束位置,因此其為可選的。結束偏移量在最後一個符號之後,例如可以使用
source_line[node.col_offset:node.end_col_offset]
來取得單列運算式節點 (expression node) 的原始片段。
ast.T
類別的建構函式按以下方式剖析其引數:如果有位置引數,則必須與
T._fields
中的項目一樣多;它們將被賦値為這些名稱的屬性。如果有關鍵字引數,它們會將相同名稱的屬性設定為給定值。
例如,要建立並填充 (populate)
ast.UnaryOp
節點,你可以使用:node=ast.UnaryOp(ast.USub(),ast.Constant(5,lineno=0,col_offset=0),lineno=0,col_offset=0)
如果建構函式中省略了文法中可選的欄位,則它預設為
None
。如果省略串列欄位,則預設為空串列。如果省略ast.expr_context
型別的欄位,則預設為Load()
。如果省略任何其他欄位,則會引發DeprecationWarning
,且 AST 節點將沒有此欄位。在 Python 3.15 中,這種情況會引發錯誤。
在 3.8 版的變更:ast.Constant
類別現在用於所有常數。
在 3.9 版的變更:以它們的值表示簡單索引,擴充切片 (slice) 則以元組 (tuple) 表示。
在 3.8 版之後被棄用:舊的類別ast.Num
、ast.Str
、ast.Bytes
、ast.NameConstant
和ast.Ellipsis
仍然可用,但它們將在未來的 Python 釋出版本中移除。與此同時,實例化它們將回傳不同類別的實例。
在 3.9 版之後被棄用:舊的類別ast.Index
和ast.ExtSlice
仍然可用,但它們將在未來的 Python 版本中刪除。同時,實例化它們會回傳不同類別的實例。
Deprecated since version 3.13, will be removed in version 3.15:先前版本的 Python 允許建立缺少必填欄位的 AST 節點。同樣地,AST 節點建構函式允許將任意關鍵字引數設為 AST 節點的屬性,即使它們與 AST 節點的任何欄位都不匹配。此行為已被棄用,並將在 Python 3.15 中刪除。
備註
這裡顯示的特定節點類別的描述最初是從出色的Green Tree Snakes 專案和所有貢獻者那裡改編而來的。
根節點¶
- classast.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))])
- 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
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
節點,表示值的格式,若未指定格式則為None
。conversion
和format_spec
可以同時設定。
- classast.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')]))]))
- classast.List(elts,ctx)¶
- classast.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()))
- 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)。
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())]))
變數¶
- 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) 中的一個其他節點: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())))])
- classast.UnaryOp(op,operand)¶
一元運算 (unary operation)。
op
是運算子,operand
是任何運算式節點。
- classast.UAdd¶
- classast.USub¶
- classast.Not¶
- classast.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())))
- classast.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())))
- 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'。
op
是Or
或And
。values
是有所涉及的值。使用同一運算子的連續操作(例如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.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
是該函式,通常是一個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()))]))
- 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.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()))
- classast.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)¶
- classast.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()))
- classast.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)¶
- classast.ListComp(elt,generators)¶
- classast.SetComp(elt,generators)¶
- classast.GeneratorExp(elt,generators)¶
- classast.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)]))
- classast.comprehension(target,iter,ifs,is_async)¶
綜合運算中的一個
for
子句。target
是用於每個元素的參照 - 通常是Name
或Tuple
節點。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
中放置一個Tuple
或List
來表示的。- 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
是單個節點,可以是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 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
。在下面的範例中,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))])
- classast.Raise(exc,cause)¶
一個
raise
陳述式。exc
是要引發的例外物件,通常是Call
或Name
,若是獨立的raise
則為None
。cause
是raisexfromy
中的可選部分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
是節點串列,例如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())])])
- 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 陳述式。
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')])])
- classast.ImportFrom(module,names,level)¶
代表
fromximporty
。module
是 'from' 名稱的原始字串,前面沒有任何的點 (dot),或者對於諸如from.importfoo
之類的陳述式則為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)])
- 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
節點。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))])])])
- classast.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))])])
- 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¶
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()])])])
- classast.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))])])
- 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
,則為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()])])])
- 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_vars
是asfoo
部分的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)¶
- 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
是要與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 版被加入.
- 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
屬性包含模式成功時將綁定的名稱。如果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 版被加入.
- 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.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 參數。
- classast.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 參數。
- classast.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 參數。
函式和類別定義¶
- 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)¶
函式的引數。
- 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)¶
一個
yield
或yieldfrom
運算式。因為這些是運算式,所以如果不使用發送回來的值,則必須將它們包裝在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)¶
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'])])
- 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
情境管理器。它們分別具有與For
和With
相同的欄位。僅在AsyncFunctionDef
主體中有效。
備註
當字串被ast.parse()
剖析時,回傳樹的運算子節點(ast.operator
、ast.unaryop
、ast.cmpop
、:class:ast.boolop
和ast.expr_context
)將是單例。對其中之一的更改將反映在所有其他出現的相同值中(例如ast.Add
)。
ast
輔助程式¶
除了節點類別之外,ast
模組還定義了這些用於遍歷 (traverse) 抽象語法樹的實用函式和類別:
- ast.parse(source,filename='<unknown>',mode='exec',*,type_comments=False,feature_version=None,optimize=-1)¶
將原始碼剖析為 AST 節點,相當於
compile(source,filename,mode,flags=FLAGS_VALUE,optimize=optimize)
,其中FLAGS_VALUE
在optimize<=0
時為ast.PyCF_ONLY_AST
,否則為ast.PyCF_OPTIMIZED_AST
。如果給定
type_comments=True
,剖析器將被修改為檢查並回傳PEP 484 和PEP 526 指定的型別註釋。這相當於將ast.PyCF_TYPE_COMMENTS
新增到傳遞給compile()
的旗標中。這將報告錯誤型別註釋的語法錯誤。如果沒有此旗標,型別註釋將被忽略,並且所選 AST 節點上的type_comment
欄位將始終為None
。此外,#type:ignore
註釋的位置將作為Module
的type_ignores
屬性回傳(否則它始終是一個空串列)。此外,如果
mode
是'func_type'
,則輸入語法將會依據PEP 484「簽名型別註解 (signature type comments)」而被修改,例如(str,int)->List[str]
。將
feature_version
設定為元組(major,minor)
將「盡可能」嘗試使用該 Python 版本的文法進行剖析。目前major
必須等於3
。例如,設定feature_version=(3,9)
將嘗試禁止剖析match
陳述式。目前major
必須為3
、支援的最低版本為(3,7)
(這在未來的 Python 版本中可能會增加);最高的是sys.version_info[0:2]
。「盡可能」嘗試意味著不能保證剖析(或剖析的成功)與在與feature_version
對應的 Python 版本上運行時相同。如果來源包含 null 字元 (
\0
),則會引發ValueError
。警告
請注意,成功將原始碼剖析為 AST 物件並不能保證提供的原始碼是可以執行的有效 Python 程式碼,因為編譯步驟可能會引發進一步的
SyntaxError
例外。例如,原始的return42
為 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 本身),不按指定順序。如果你只想就地修改節點而不關心情境,這非常有用。
- 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_empty 為
False
(預設值),則輸出中將省略False
的空串列和欄位。在 3.9 版的變更:新增indent 選項。
在 3.13 版的變更:新增show_empty 選項。
>>>print(ast.dump(ast.parse("""\...async def f():... await other_func()..."""),indent=4,show_empty=True))Module( body=[ AsyncFunctionDef( name='f', args=arguments( posonlyargs=[], args=[], kwonlyargs=[], kw_defaults=[], defaults=[]), body=[ Expr( value=Await( value=Call( func=Name(id='other_func', ctx=Load()), args=[], keywords=[])))], decorator_list=[], type_params=[])], type_ignores=[])
編譯器旗標¶
可以將以下旗標傳遞給compile()
以變更對程式的編譯效果:
- ast.PyCF_ALLOW_TOP_LEVEL_AWAIT¶
啟用對最高階
await
、asyncfor
、asyncwith
和非同步綜合運算的支援。在 3.8 版被加入.
- ast.PyCF_ONLY_AST¶
生成並回傳抽象語法樹,而不是回傳已編譯的程式碼物件。
- ast.PyCF_OPTIMIZED_AST¶
回傳的 AST 會根據
compile()
或ast.parse()
中的optimize 引數進行最佳化。在 3.13 版被加入.
命令列用法¶
在 3.9 版被加入.
ast
模組可以作為腳本從命令列執行,可以像這樣簡單地做到:
python-mast[-m<mode>][-a][infile]
以下選項可被接受:
- -h,--help¶
顯示幫助訊息並退出。
- --no-type-comments¶
不要剖析型別註解。
- -a,--include-attributes¶
包括列號和行偏移量等屬性。
如果指定了infile
,則其內容將被剖析為 AST 並傾印 (dump) 到 stdout。否則會從 stdin 讀取內容。
也參考
Green Tree Snakes 是一個外部文件資源,提供了有關使用 Python AST 的詳細資訊。
ASTTokens 使用生成它們的原始碼中的標記和文本的位置來註釋 Python AST。這對於進行原始碼轉換的工具很有幫助。
leoAst.py 透過在 token 和 ast 節點之間插入雙向鏈結,統一了 python 程式的基於 token 和基於剖析樹的視圖。
LibCST 將程式碼剖析為具體語法樹 (Concrete Syntax Tree),看起來像 ast 樹並保留所有格式詳細資訊。它對於建置自動重構 (codemod) 應用程式和 linter 非常有用。
Parso 是一個 Python 剖析器,支援不同 Python 版本的錯誤復原和往返剖析。Parso 還能夠列出 Python 檔案中的多個語法錯誤。