ast — 추상 구문 트리
ast — 추상 구문 트리 (Abstract syntax trees)
Python 추상 구문 문법(abstract syntax grammar)의 트리를 처리할 수 있게 해주는 모듈이에요. 추상 구문 자체는 Python 릴리스마다 바뀔 수 있는데, 이 모듈은 현재 문법이 어떤 모양인지 프로그래밍 방식으로 알아내는 데 도움을 줘요.
출처: Python 표준 라이브러리
본문
ast 모듈은 Python 애플리케이션이 Python 추상 구문 문법의 트리를 처리하도록 도와줘요. 추상 구문 자체는 Python 릴리스마다 바뀔 수 있어서, 이 모듈은 현재 문법이 어떤 모양인지 프로그래밍 방식으로 알아내는 데 도움을 줘요.
추상 구문 트리는 내장 compile() 함수에 플래그로 ast.PyCF_ONLY_AST를 전달하거나, 이 모듈이 제공하는 parse() 헬퍼를 사용해 생성할 수 있어요. 결과는 모든 클래스가 ast.AST에서 상속받는 객체들의 트리가 돼요. 추상 구문 트리는 내장 compile() 함수로 Python 코드 객체로 컴파일될 수 있어요.
추상 문법 (Abstract grammar)
현재 추상 문법은 다음과 같이 정의돼요:
-- ASDL's 4 builtin types are:
-- identifier, int, string, constant
module Python
{
mod = Module(stmt* body, type_ignore* type_ignores)
| Interactive(stmt* body)
| Expression(expr body)
| FunctionType(expr* argtypes, expr returns)
stmt = FunctionDef(identifier name, arguments args,
stmt* body, expr* decorator_list, expr? returns,
string? type_comment, type_param* type_params)
| AsyncFunctionDef(identifier name, arguments args,
stmt* body, expr* decorator_list, expr? returns,
string? type_comment, type_param* type_params)
| ClassDef(identifier name,
expr* bases,
keyword* keywords,
stmt* body,
expr* decorator_list,
type_param* type_params)
| Return(expr? value)
| Delete(expr* targets)
| Assign(expr* targets, expr value, string? type_comment)
| TypeAlias(expr name, type_param* type_params, expr value)
| AugAssign(expr target, operator op, expr value)
-- 'simple' indicates that we annotate simple name without parens
| AnnAssign(expr target, expr annotation, expr? value, int simple)
-- use 'orelse' because else is a keyword in target languages
| For(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment)
| AsyncFor(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment)
| While(expr test, stmt* body, stmt* orelse)
| If(expr test, stmt* body, stmt* orelse)
| With(withitem* items, stmt* body, string? type_comment)
| AsyncWith(withitem* items, stmt* body, string? type_comment)
| Match(expr subject, match_case* cases)
| Raise(expr? exc, expr? cause)
| Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)
| TryStar(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)
| Assert(expr test, expr? msg)
| Import(alias* names)
| ImportFrom(identifier? module, alias* names, int? level)
| Global(identifier* names)
| Nonlocal(identifier* names)
| Expr(expr value)
| Pass | Break | Continue
-- col_offset is the byte offset in the utf8 string the parser uses
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
-- BoolOp() can use left right?
expr = BoolOp(boolop op, expr* values)
| NamedExpr(expr target, expr value)
| BinOp(expr left, operator op, expr right)
| UnaryOp(unaryop op, expr operand)
| Lambda(arguments args, expr body)
| IfExp(expr test, expr body, expr orelse)
| Dict(expr?* keys, expr* values)
| Set(expr* elts)
| ListComp(expr elt, comprehension* generators)
| SetComp(expr elt, comprehension* generators)
| DictComp(expr key, expr value, comprehension* generators)
| GeneratorExp(expr elt, comprehension* generators)
-- the grammar constrains where yield expressions can occur
| Await(expr value)
| Yield(expr? value)
| YieldFrom(expr value)
-- need sequences for compare to distinguish between
-- x 4 3 and (x 4) 3
| Compare(expr left, cmpop* ops, expr* comparators)
| Call(expr func, expr* args, keyword* keywords)
| FormattedValue(expr value, int conversion, expr? format_spec)
| Interpolation(expr value, constant str, int conversion, expr? format_spec)
| JoinedStr(expr* values)
| TemplateStr(expr* values)
| Constant(constant value, string? kind)
-- the following expression can appear in assignment context
| Attribute(expr value, identifier attr, expr_context ctx)
| Subscript(expr value, expr slice, expr_context ctx)
| Starred(expr value, expr_context ctx)
| Name(identifier id, expr_context ctx)
| List(expr* elts, expr_context ctx)
| Tuple(expr* elts, expr_context ctx)
-- can appear only in Subscript
| Slice(expr? lower, expr? upper, expr? step)
-- col_offset is the byte offset in the utf8 string the parser uses
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
expr_context = Load | Store | Del
boolop = And | Or
operator = Add | Sub | Mult | MatMult | Div | Mod | Pow | LShift
| RShift | BitOr | BitXor | BitAnd | FloorDiv
unaryop = Invert | Not | UAdd | USub
cmpop = Eq | NotEq | Lt | LtE | Gt | GtE | Is | IsNot | In | NotIn
comprehension = (expr target, expr iter, expr* ifs, int is_async)
excepthandler = ExceptHandler(expr? type, identifier? name, stmt* body)
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
arguments = (arg* posonlyargs, arg* args, arg? vararg, arg* kwonlyargs,
expr?* kw_defaults, arg? kwarg, expr* defaults)
arg = (identifier arg, expr? annotation, string? type_comment)
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
-- keyword arguments supplied to call (NULL identifier for **kwargs)
keyword = (identifier? arg, expr value)
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
-- import name with optional 'as' alias.
alias = (identifier name, identifier? asname)
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
withitem = (expr context_expr, expr? optional_vars)
match_case = (pattern pattern, expr? guard, stmt* body)
pattern = MatchValue(expr value)
| MatchSingleton(constant value)
| MatchSequence(pattern* patterns)
| MatchMapping(expr* keys, pattern* patterns, identifier? rest)
| MatchClass(expr cls, pattern* patterns, identifier* kwd_attrs, pattern* kwd_patterns)
| MatchStar(identifier? name)
-- The optional "rest" MatchMapping parameter handles capturing extra mapping keys
| MatchAs(pattern? pattern, identifier? name)
| MatchOr(pattern* patterns)
attributes (int lineno, int col_offset, int end_lineno, int end_col_offset)
type_ignore = TypeIgnore(int lineno, string tag)
type_param = TypeVar(identifier name, expr? bound, expr? default_value)
| ParamSpec(identifier name, expr? default_value)
| TypeVarTuple(identifier name, expr? default_value)
attributes (int lineno, int col_offset, int end_lineno, int end_col_offset)
}
노드 클래스 (Node classes)
class ast.AST
이것은 모든 AST 노드 클래스의 기반이에요. 실제 노드 클래스는 위에 재현돼 있는 Parser/Python.asdl 파일에서 파생돼요. 그것들은 _ast C 모듈에 정의되고 ast에서 다시 내보내져요.
추상 문법의 각 좌변(left-hand side) 기호에 대해 하나의 클래스가 정의돼요(예: ast.stmt 또는 ast.expr). 게다가 각 우변(right-hand side) 생성자에 대해 하나의 클래스가 정의돼요. 이 클래스들은 좌변 트리의 클래스에서 상속받아요. 예를 들어 ast.BinOp는 ast.expr에서 상속받아요. 대안(aka "sums")이 있는 생성 규칙의 경우 좌변 클래스는 추상적이에요. 특정 생성자 노드의 인스턴스만 생성돼요.
_fields— 각 구상(concrete) 클래스에는 모든 자식 노드의 이름을 주는_fields속성이 있어요. 각 구상 클래스의 인스턴스는 문법에 정의된 대로 각 자식 노드에 대해 하나의 속성을 가져요. 예를 들어ast.BinOp인스턴스는 타입ast.expr의left속성을 가져요. 이 속성이 문법에서 선택적(물음표)으로 표시되면 값은None일 수 있어요. 속성이 0개 이상의 값을 가질 수 있으면(별표 표시) 값은 Python 리스트로 표현돼요.compile()로 AST를 컴파일할 때 모든 가능한 속성이 존재하고 유효한 값을 가져야 해요._field_types— 각 구상 클래스의_field_types속성은 필드 이름(_fields에도 나열된)을 타입에 매핑하는 사전이에요.
3.13 버전에서 추가.>>> ast.TypeVar._field_types {'name': <class 'str'>, 'bound': ast.expr | None, 'default_value': ast.expr | None}lineno/col_offset/end_lineno/end_col_offset—ast.expr와ast.stmt서브클래스의 인스턴스는lineno,col_offset,end_lineno,end_col_offset속성을 가져요.lineno와end_lineno는 소스 텍스트 범위의 첫 번째와 마지막 줄 번호(1-기반이라 첫 줄은 1)이고,col_offset과end_col_offset은 노드를 생성한 첫 번째와 마지막 토큰의 대응하는 UTF-8 바이트 오프셋이에요. 파서가 내부적으로 UTF-8을 사용하므로 UTF-8 오프셋이 기록돼요. 끝 위치는 컴파일러가 요구하지 않으므로 선택적이라는 점을 참고하세요. 끝 오프셋은 마지막 기호 뒤에 있어요. 예를 들어 한 줄 표현식 노드의 소스 세그먼트는source_line[node.col_offset : node.end_col_offset]로 얻을 수 있어요.
클래스 ast.T의 생성자는 인자를 다음과 같이 파싱해요:
- 위치 인자가 있으면
T._fields의 항목 수만큼 있어야 하고, 이 이름들의 속성으로 할당돼요. - 키워드 인자가 있으면 같은 이름의 속성을 주어진 값으로 설정해요.
예를 들어 ast.UnaryOp 노드를 생성하고 채우려면 다음을 사용할 수 있어요:
node = ast.UnaryOp(ast.USub(), ast.Constant(5, lineno=0, col_offset=0),
lineno=0, col_offset=0)
문법에서 선택적인 필드가 생성자에서 생략되면 None으로 기본 설정돼요. 리스트 필드가 생략되면 빈 리스트로 기본 설정돼요. ast.expr_context 타입의 필드가 생략되면 Load()로 기본 설정돼요. 다른 필드가 생략되면 DeprecationWarning이 발생하고 AST 노드에 이 필드가 없게 돼요. Python 3.15에서는 이 조건이 오류를 발생시켜요.
3.8 버전 변경: 모든 상수에
ast.Constant클래스가 사용돼요.3.9 버전 변경: 단순 인덱스는 그 값으로 표현되고, 확장 슬라이스는 튜플로 표현돼요.
3.13 버전 변경: AST 노드 생성자가 생략된 필드에 합리적인 기본값을 제공하도록 변경됐어요. 선택 필드는 이제
None으로, 리스트 필드는 빈 리스트로,ast.expr_context타입의 필드는Load()로 기본 설정돼요. 이전에는 생략된 속성이 생성된 노드에 존재하지 않았어요(접근 시AttributeError발생).3.14 버전 변경: AST 노드의
__repr__()출력이 노드 필드의 값을 포함해요.3.8부터 deprecated, 3.14에서 제거: 이전 Python 버전은
ast.Num,ast.Str,ast.Bytes,ast.NameConstant,ast.EllipsisAST 클래스를 제공했는데, 이것들은 Python 3.8에서 deprecated됐어요. 이 클래스들은 Python 3.14에서 제거됐고, 그 기능은ast.Constant로 대체됐어요.3.9부터 deprecated: 옛 클래스
ast.Index와ast.ExtSlice는 여전히 사용 가능하지만 미래의 Python 릴리스에서 제거될 거예요. 그동안 그것들을 인스턴스화하면 다른 클래스의 인스턴스가 반환돼요.3.13부터 deprecated, 3.15에서 제거 예정: 이전 Python 버전은 필수 필드가 없는 AST 노드 생성과, AST 노드의 필드와 일치하지 않는 임의의 키워드 인자를 AST 노드의 속성으로 설정하는 것을 허용했어요. 이 동작은 deprecated이며 Python 3.15에서 제거될 거예요.
참고: 여기 표시된 특정 노드 클래스의 설명은 처음에 훌륭한 Green Tree Snakes 프로젝트와 그 모든 기여자들로부터 채택됐어요.
루트 노드 (Root nodes)
class ast.Module(body, type_ignores)
파일 입력과 같은 Python 모듈. 기본 exec 모드에서 ast.parse()가 생성하는 노드 타입이에요. body는 모듈의 명령문(Statements) 리스트예요. type_ignores는 모듈의 타입 무시 주석 리스트예요. 자세한 내용은 ast.parse()를 참고하세요.
>>> print(ast.dump(ast.parse('x = 1'), indent=4))
Module(
body=[
Assign(
targets=[
Name(id='x', ctx=Store())],
value=Constant(value=1))])
class ast.Expression(body)
단일 Python 표현식 입력. mode가 eval일 때 ast.parse()가 생성하는 노드 타입이에요. body는 표현식 타입 중 하나의 단일 노드예요.
>>> print(ast.dump(ast.parse('123', mode='eval'), indent=4))
Expression(
body=Constant(value=123))
class ast.Interactive(body)
인터랙티브 모드(Interactive Mode) 같은 단일 대화형 입력. mode가 single일 때 ast.parse()가 생성하는 노드 타입이에요. body는 명령문 노드의 리스트예요.
>>> print(ast.dump(ast.parse('x = 1; y = 2', mode='single'), indent=4))
Interactive(
body=[
Assign(
targets=[
Name(id='x', ctx=Store())],
value=Constant(value=1)),
Assign(
targets=[
Name(id='y', ctx=Store())],
value=Constant(value=2))])
class ast.FunctionType(argtypes, returns)
Python 3.5 이전 버전이 PEP 484 애너테이션을 지원하지 않았으므로, 함수에 대한 옛 스타일 타입 주석의 표현. mode가 func_type일 때 ast.parse()가 생성하는 노드 타입이에요.
그런 타입 주석은 이렇게 생겼어요:
def sum_two_number(a, b):
# type: (int, int) -> int
return a + b
argtypes는 표현식 노드의 리스트예요. returns는 단일 표현식 노드예요.
>>> print(ast.dump(ast.parse('(int, str) -> List[int]', mode='func_type'), indent=4))
FunctionType(
argtypes=[
Name(id='int', ctx=Load()),
Name(id='str', ctx=Load())],
returns=Subscript(
value=Name(id='List', ctx=Load()),
slice=Name(id='int', ctx=Load()),
ctx=Load()))
3.8 버전에서 추가.
리터럴 (Literals)
class ast.Constant(value, kind)
상수 값. Constant 리터럴의 value 속성은 그것이 나타내는 Python 객체를 담아요. 표현되는 값은 str, bytes, int, float, complex, bool의 인스턴스와 상수 None과 Ellipsis일 수 있어요.
kind 속성은 선택적 문자열이에요. u 접두사가 있는 문자열 리터럴의 경우 kind는 'u'로 설정돼요. 다른 모든 상수에 대해 kind는 None이에요.
>>> print(ast.dump(ast.parse('123', mode='eval'), indent=4))
Expression(
body=Constant(value=123))
>>> print(ast.dump(ast.parse("u'hello'", mode='eval'), indent=4))
Expression(
body=Constant(value='hello', kind='u'))
class ast.FormattedValue(value, conversion, format_spec)
f-문자열에서 단일 포매팅 필드를 나타내는 노드. 문자열이 단일 포매팅 필드만 포함하고 다른 게 없으면 노드가 단독으로 존재할 수 있고, 그렇지 않으면 JoinedStr 안에 나타나요. value는 어떤 표현식 노드(리터럴, 변수, 함수 호출 등)든 가능해요. conversion은 정수예요:
-1: 포매팅 없음97(ord('a')):!aASCII 포매팅114(ord('r')):!rrepr() 포매팅115(ord('s')):!s문자열 포매팅
format_spec은 값의 포매팅을 나타내는 JoinedStr 노드이거나, 형식이 지정되지 않았으면 None이에요. conversion과 format_spec은 동시에 설정될 수 있어요.
class ast.JoinedStr(values)
일련의 FormattedValue와 Constant 노드로 구성된 f-문자열.
>>> print(ast.dump(ast.parse('f"sin({a}) is {sin(a):.3}"', mode='eval'), indent=4))
Expression(
body=JoinedStr(
values=[
Constant(value='sin('),
FormattedValue(
value=Name(id='a', ctx=Load()),
conversion=-1),
Constant(value=') is '),
FormattedValue(
value=Call(
func=Name(id='sin', ctx=Load()),
args=[
Name(id='a', ctx=Load())]),
conversion=-1,
format_spec=JoinedStr(
values=[
Constant(value='.3')]))]))
class ast.TemplateStr(values, /)
3.14 버전에서 추가. 일련의 Interpolation과 Constant 노드로 구성된 템플릿 문자열 리터럴을 나타내는 노드. 이 노드들은 어떤 순서로도 될 수 있고, 반드시 교차할 필요는 없어요.
>>> expr = ast.parse('t"{name} finished {place:ordinal}"', mode='eval')
>>> print(ast.dump(expr, indent=4))
Expression(
body=TemplateStr(
values=[
Interpolation(
value=Name(id='name', ctx=Load()),
str='name',
conversion=-1),
Constant(value=' finished '),
Interpolation(
value=Name(id='place', ctx=Load()),
str='place',
conversion=-1,
format_spec=JoinedStr(
values=[
Constant(value='ordinal')]))]))
class ast.Interpolation(value, str, conversion, format_spec=None)
3.14 버전에서 추가. 템플릿 문자열 리터럴에서 단일 보간(interpolation) 필드를 나타내는 노드. value는 어떤 표현식 노드든 가능하고 FormattedValue.value와 같은 의미예요. str은 보간 표현식의 텍스트를 담은 상수예요. str이 None으로 설정되면 ast.unparse()를 호출할 때 코드를 생성하는 데 value가 사용돼요. 이는 생성된 코드가 원본과 동일하다는 것을 더 이상 보장하지 않으며 코드 생성용으로 의도됐어요. conversion은 -1(변환 없음), 97(!a ASCII 변환), 114(!r repr() 변환), 115(!s 문자열 변환)의 정수이고 FormattedValue.conversion과 같은 의미예요. format_spec은 값의 포매팅을 나타내는 JoinedStr 노드이거나, 형식이 지정되지 않았으면 None이에요. FormattedValue.format_spec과 같은 의미예요.
class ast.List(elts, ctx) / class ast.Tuple(elts, ctx)
리스트 또는 튜플. elts는 요소를 나타내는 노드 리스트를 담아요. ctx는 컨테이너가 할당 대상(즉 (x,y)=something)이면 Store이고, 그렇지 않으면 Load예요.
>>> print(ast.dump(ast.parse('[1, 2, 3]', mode='eval'), indent=4))
Expression(
body=List(
elts=[
Constant(value=1),
Constant(value=2),
Constant(value=3)],
ctx=Load()))
>>> print(ast.dump(ast.parse('(1, 2, 3)', mode='eval'), indent=4))
Expression(
body=Tuple(
elts=[
Constant(value=1),
Constant(value=2),
Constant(value=3],
ctx=Load()))
class ast.Set(elts)
집합. elts는 집합 요소를 나타내는 노드 리스트를 담아요.
>>> print(ast.dump(ast.parse('{1, 2, 3}', mode='eval'), indent=4))
Expression(
body=Set(
elts=[
Constant(value=1),
Constant(value=2),
Constant(value=3)]))
class ast.Dict(keys, values)
딕셔너리. keys와 values는 각각 딕셔너리의 키와 값을 나타내는 노드 리스트를 일치하는 순서로 담아요(딕셔너리 keys()와 values()를 호출할 때 반환되는 것처럼). 딕셔너리 리터럴을 사용해 딕셔너리 언패킹을 할 때 확장할 표현식은 values 리스트에 들어가고, keys의 대응하는 위치에는 None이 들어가요.
>>> print(ast.dump(ast.parse('{"a":1, **d}', mode='eval'), indent=4))
Expression(
body=Dict(
keys=[
Constant(value='a'),
None],
values=[
Constant(value=1),
Name(id='d', ctx=Load())]))
변수 (Variables)
class ast.Name(id, ctx)
변수 이름. id는 이름을 문자열로 담고, ctx는 다음 타입 중 하나예요.
class ast.Load / class ast.Store / class ast.Del
변수 참조는 변수의 값을 로드하고, 새 값을 할당하고, 삭제하는 데 사용될 수 있어요. 변수 참조에는 이 경우들을 구분하기 위해 컨텍스트가 주어져요.
>>> print(ast.dump(ast.parse('a'), indent=4))
Module(
body=[
Expr(
value=Name(id='a', ctx=Load()))])
>>> print(ast.dump(ast.parse('a = 1'), indent=4))
Module(
body=[
Assign(
targets=[
Name(id='a', ctx=Store())],
value=Constant(value=1))])
>>> print(ast.dump(ast.parse('del a'), indent=4))
Module(
body=[
Delete(
targets=[
Name(id='a', ctx=Del())])])
class ast.Starred(value, ctx)
*var 변수 참조. value는 변수(보통 Name 노드)를 담아요. 이 타입은 *args로 Call 노드를 만들 때 사용해야 해요.
>>> print(ast.dump(ast.parse('a, *b = it'), indent=4))
Module(
body=[
Assign(
targets=[
Tuple(
elts=[
Name(id='a', ctx=Store()),
Starred(
value=Name(id='b', ctx=Store()),
ctx=Store())],
ctx=Store())],
value=Name(id='it', ctx=Load()))])
표현식 (Expressions)
class ast.Expr(value)
함수 호출 같은 표현식이 반환값을 사용하거나 저장하지 않고 명령문으로 단독으로 나타날 때, 이 컨테이너로 감싸져요. value는 이 섹션의 다른 노드 중 하나, Constant, Name, Lambda, Yield 또는 YieldFrom 노드를 담아요.
>>> print(ast.dump(ast.parse('-a'), indent=4))
Module(
body=[
Expr(
value=UnaryOp(
op=USub(),
operand=Name(id='a', ctx=Load()))])
class ast.UnaryOp(op, operand)
단항 연산. op는 연산자이고, operand는 어떤 표현식 노드든 가능해요.
class ast.UAdd / class ast.USub / class ast.Not / class ast.Invert
단항 연산자 토큰. Not은 not 키워드, Invert는 ~ 연산자예요.
>>> print(ast.dump(ast.parse('not x', mode='eval'), indent=4))
Expression(
body=UnaryOp(
op=Not(),
operand=Name(id='x', ctx=Load())))
class ast.BinOp(left, op, right)
이항 연산(덧셈이나 나눗셈 같은). op는 연산자이고, left와 right는 어떤 표현식 노드든 가능해요.
>>> print(ast.dump(ast.parse('x + y', mode='eval'), indent=4))
Expression(
body=BinOp(
left=Name(id='x', ctx=Load()),
op=Add(),
right=Name(id='y', ctx=Load())))
class ast.Add / class ast.Sub / class ast.Mult / class ast.Div / class ast.FloorDiv / class ast.Mod / class ast.Pow / class ast.LShift / class ast.RShift / class ast.BitOr / class ast.BitXor / class ast.BitAnd / class ast.MatMult
이항 연산자 토큰.
class ast.BoolOp(op, values)
불리언 연산, 'or' 또는 'and'. op는 Or 또는 And예요. values는 관련된 값들이에요. a or b or c 같은 같은 연산자를 가진 연속 연산은 여러 값이 있는 하나의 노드로 합쳐져요. 이것은 UnaryOp인 not을 포함하지 않아요.
>>> print(ast.dump(ast.parse('x or y', mode='eval'), indent=4))
Expression(
body=BoolOp(
op=Or(),
values=[
Name(id='x', ctx=Load()),
Name(id='y', ctx=Load())]))
class ast.And / class ast.Or
불리언 연산자 토큰.
class ast.Compare(left, ops, comparators)
두 개 이상 값의 비교. left는 비교의 첫 번째 값, ops는 연산자 리스트, comparators는 비교의 첫 요소 뒤의 값 리스트예요.
>>> print(ast.dump(ast.parse('1 <= a < 10', mode='eval'), indent=4))
Expression(
body=Compare(
left=Constant(value=1),
ops=[
LtE(),
Lt()],
comparators=[
Name(id='a', ctx=Load()),
Constant(value=10)]))
class ast.Eq / class ast.NotEq / class ast.Lt / class ast.LtE / class ast.Gt / class ast.GtE / class ast.Is / class ast.IsNot / class ast.In / class ast.NotIn
비교 연산자 토큰.
class ast.Call(func, args, keywords)
함수 호출. func는 함수로, 보통 Name 또는 Attribute 객체예요. 인자 중: args는 위치로 전달된 인자의 리스트를 담아요. keywords는 키워드로 전달된 인자를 나타내는 keyword 객체 리스트를 담아요. args와 keywords 인자는 선택적이며 기본값은 빈 리스트예요.
>>> print(ast.dump(ast.parse('func(a, b=c, *d, **e)', mode='eval'), indent=4))
Expression(
body=Call(
func=Name(id='func', ctx=Load()),
args=[
Name(id='a', ctx=Load()),
Starred(
value=Name(id='d', ctx=Load()),
ctx=Load())],
keywords=[
keyword(
arg='b',
value=Name(id='c', ctx=Load())),
keyword(
value=Name(id='e', ctx=Load()))]))
class ast.keyword(arg, value)
함수 호출이나 클래스 정의에 대한 키워드 인자. arg는 매개변수 이름의 원시 문자열이고, value는 전달할 노드예요.
class ast.IfExp(test, body, orelse)
a if b else c 같은 표현식. 각 필드는 단일 노드를 담아서, 다음 예시에서 세 개 모두 Name 노드예요.
>>> print(ast.dump(ast.parse('a if b else c', mode='eval'), indent=4))
Expression(
body=IfExp(
test=Name(id='b', ctx=Load()),
body=Name(id='a', ctx=Load()),
orelse=Name(id='c', ctx=Load())))
class ast.Attribute(value, attr, ctx)
d.keys 같은 속성 접근. value는 보통 Name인 노드예요. attr은 속성의 이름을 주는 원시 문자열이고, ctx는 속성이 어떻게 작용되는지에 따라 Load, Store 또는 Del이에요.
>>> print(ast.dump(ast.parse('snake.colour', mode='eval'), indent=4))
Expression(
body=Attribute(
value=Name(id='snake', ctx=Load()),
attr='colour',
ctx=Load()))
class ast.NamedExpr(target, value)
명명된 표현식. 이 AST 노드는 할당 표현식 연산자(월러스 연산자라고도 함)로 생성돼요. 첫 번째 인자가 여러 노드일 수 있는 Assign 노드와 달리, 이 경우 target과 value 모두 단일 노드여야 해요.
>>> print(ast.dump(ast.parse('(x := 4)', mode='eval'), indent=4))
Expression(
body=NamedExpr(
target=Name(id='x', ctx=Store()),
value=Constant(value=4)))
3.8 버전에서 추가.
서브스크립팅 (Subscripting)
class ast.Subscript(value, slice, ctx)
l[1] 같은 서브스크립트. value는 서브스크립트되는 객체(보통 시퀀스나 매핑)예요. slice는 인덱스, 슬라이스 또는 키예요. Tuple일 수 있고 Slice를 포함할 수 있어요. ctx는 서브스크립트로 수행된 동작에 따라 Load, Store 또는 Del이에요.
>>> print(ast.dump(ast.parse('l[1:2, 3]', mode='eval'), indent=4))
Expression(
body=Subscript(
value=Name(id='l', ctx=Load()),
slice=Tuple(
elts=[
Slice(
lower=Constant(value=1),
upper=Constant(value=2)),
Constant(value=3)],
ctx=Load()),
ctx=Load()))
class ast.Slice(lower, upper, step)
일반 슬라이싱(lower:upper 또는 lower:upper:step 형태). Subscript의 slice 필드 안에서만, 직접 또는 Tuple의 요소로 나타날 수 있어요.
>>> print(ast.dump(ast.parse('l[1:2]', mode='eval'), indent=4))
Expression(
body=Subscript(
value=Name(id='l', ctx=Load()),
slice=Slice(
lower=Constant(value=1),
upper=Constant(value=2)),
ctx=Load()))
컴프리헨션 (Comprehensions)
class ast.ListComp(elt, generators) / class ast.SetComp(elt, generators) / class ast.GeneratorExp(elt, generators) / class ast.DictComp(key, value, generators)
리스트·집합 컴프리헨션, 제너레이터 표현식, 딕셔너리 컴프리헨션. elt(또는 key와 value)는 각 항목에 대해 평가될 부분을 나타내는 단일 노드예요. generators는 comprehension 노드의 리스트예요.
>>> print(ast.dump(
... ast.parse('[x for x in numbers]', mode='eval'),
... indent=4,
... ))
Expression(
body=ListComp(
elt=Name(id='x', ctx=Load()),
generators=[
comprehension(
target=Name(id='x', ctx=Store()),
iter=Name(id='numbers', ctx=Load()),
is_async=0)]))
>>> print(ast.dump(
... ast.parse('{x: x**2 for x in numbers}', mode='eval'),
... indent=4,
... ))
Expression(
body=DictComp(
key=Name(id='x', ctx=Load()),
value=BinOp(
left=Name(id='x', ctx=Load()),
op=Pow(),
right=Constant(value=2)),
generators=[
comprehension(
target=Name(id='x', ctx=Store()),
iter=Name(id='numbers', ctx=Load()),
is_async=0)]))
>>> print(ast.dump(
... ast.parse('{x for x in numbers}', mode='eval'),
... indent=4,
... ))
Expression(
body=SetComp(
elt=Name(id='x', ctx=Load()),
generators=[
comprehension(
target=Name(id='x', ctx=Store()),
iter=Name(id='numbers', ctx=Load()),
is_async=0)]))
class ast.comprehension(target, iter, ifs, is_async)
컴프리헨션에서 하나의 for 절. target은 각 요소에 사용할 참조로, 보통 Name 또는 Tuple 노드예요. iter는 반복할 객체예요. ifs는 테스트 표현식 리스트예요. 각 for 절은 여러 ifs를 가질 수 있어요. is_async는 컴프리헨션이 비동기적인지(for 대신 async for 사용) 나타내요. 값은 정수(0 또는 1)예요.
>>> print(ast.dump(ast.parse('[ord(c) for line in file for c in line]', mode='eval'),
... indent=4)) # Multiple comprehensions in one.
Expression(
body=ListComp(
elt=Call(
func=Name(id='ord', ctx=Load()),
args=[
Name(id='c', ctx=Load())]),
generators=[
comprehension(
target=Name(id='line', ctx=Store()),
iter=Name(id='file', ctx=Load()),
is_async=0),
comprehension(
target=Name(id='c', ctx=Store()),
iter=Name(id='line', ctx=Load()),
is_async=0)]))
>>> print(ast.dump(ast.parse('(n**2 for n in it if n>5 if n<10)', mode='eval'),
... indent=4)) # generator comprehension
Expression(
body=GeneratorExp(
elt=BinOp(
left=Name(id='n', ctx=Load()),
op=Pow(),
right=Constant(value=2)),
generators=[
comprehension(
target=Name(id='n', ctx=Store()),
iter=Name(id='it', ctx=Load()),
ifs=[
Compare(
left=Name(id='n', ctx=Load()),
ops=[
Gt()],
comparators=[
Constant(value=5)]),
Compare(
left=Name(id='n', ctx=Load()),
ops=[
Lt()],
comparators=[
Constant(value=10)])],
is_async=0)]))
>>> print(ast.dump(ast.parse('[i async for i in soc]', mode='eval'),
... indent=4)) # Async comprehension
Expression(
body=ListComp(
elt=Name(id='i', ctx=Load()),
generators=[
comprehension(
target=Name(id='i', ctx=Store()),
iter=Name(id='soc', ctx=Load()),
is_async=1)]))
명령문 (Statements)
class ast.Assign(targets, value, type_comment)
할당. targets는 노드 리스트이고, value는 단일 노드예요. targets의 여러 노드는 같은 값을 각각 할당하는 것을 나타내요. 언패킹은 targets 안에 Tuple 또는 List를 넣는 것으로 표현돼요.
type_comment— 타입 애너테이션을 주석으로 담은 선택적 문자열.
>>> print(ast.dump(ast.parse('a = b = 1'), indent=4)) # Multiple assignment
Module(
body=[
Assign(
targets=[
Name(id='a', ctx=Store()),
Name(id='b', ctx=Store())],
value=Constant(value=1))])
>>> print(ast.dump(ast.parse('a,b = c'), indent=4)) # Unpacking
Module(
body=[
Assign(
targets=[
Tuple(
elts=[
Name(id='a', ctx=Store()),
Name(id='b', ctx=Store())],
ctx=Store())],
value=Name(id='c', ctx=Load()))])
class ast.AnnAssign(target, annotation, value, simple)
타입 애너테이션이 있는 할당. target은 단일 노드이고 Name, Attribute 또는 Subscript일 수 있어요. annotation은 Constant 또는 Name 노드 같은 애너테이션이에요. value는 단일 선택적 노드예요.
simple은 항상 0("복잡한" 대상 표시) 또는 1("단순한" 대상 표시) 중 하나예요. "단순한" 대상은 괄호 사이에 나타나지 않는 Name 노드로만 구성돼요. 다른 모든 대상은 복잡한 것으로 간주돼요. 단순한 대상만 모듈과 클래스의 __annotations__ 딕셔너리에 나타나요.
>>> print(ast.dump(ast.parse('c: int'), indent=4))
Module(
body=[
AnnAssign(
target=Name(id='c', ctx=Store()),
annotation=Name(id='int', ctx=Load()),
simple=1)])
>>> print(ast.dump(ast.parse('(a): int = 1'), indent=4)) # Annotation with parenthesis
Module(
body=[
AnnAssign(
target=Name(id='a', ctx=Store()),
annotation=Name(id='int', ctx=Load()),
value=Constant(value=1),
simple=0)])
>>> print(ast.dump(ast.parse('a.b: int'), indent=4)) # Attribute annotation
Module(
body=[
AnnAssign(
target=Attribute(
value=Name(id='a', ctx=Load()),
attr='b',
ctx=Store()),
annotation=Name(id='int', ctx=Load()),
simple=0)])
>>> print(ast.dump(ast.parse('a[1]: int'), indent=4)) # Subscript annotation
Module(
body=[
AnnAssign(
target=Subscript(
value=Name(id='a', ctx=Load()),
slice=Constant(value=1),
ctx=Store()),
annotation=Name(id='int', ctx=Load()),
simple=0)])
class ast.AugAssign(target, op, value)
a += 1 같은 확장 할당. 다음 예시에서 target은 x에 대한 Name 노드(Store 컨텍스트), op는 Add, value는 1의 값을 가진 Constant예요. target 속성은 Assign의 targets와 달리 Tuple 또는 List 클래스일 수 없어요.
>>> print(ast.dump(ast.parse('x += 2'), indent=4))
Module(
body=[
AugAssign(
target=Name(id='x', ctx=Store()),
op=Add(),
value=Constant(value=2))])
class ast.Raise(exc, cause)
raise 명령문. exc는 발생시킬 예외 객체로, 보통 Call 또는 Name, 또는 단독 raise에 대해 None이에요. cause는 raise x from y에서 y의 선택적 부분이에요.
>>> print(ast.dump(ast.parse('raise x from y'), indent=4))
Module(
body=[
Raise(
exc=Name(id='x', ctx=Load()),
cause=Name(id='y', ctx=Load()))])
class ast.Assert(test, msg)
어서션. test는 Compare 노드 같은 조건을 담아요. msg는 실패 메시지를 담아요.
>>> print(ast.dump(ast.parse('assert x,y'), indent=4))
Module(
body=[
Assert(
test=Name(id='x', ctx=Load()),
msg=Name(id='y', ctx=Load()))])
class ast.Delete(targets)
del 명령문을 나타내요. targets는 Name, Attribute 또는 Subscript 노드 같은 노드 리스트예요.
>>> print(ast.dump(ast.parse('del x,y,z'), indent=4))
Module(
body=[
Delete(
targets=[
Name(id='x', ctx=Del()),
Name(id='y', ctx=Del()),
Name(id='z', ctx=Del())])])
class ast.Pass
pass 명령문.
>>> print(ast.dump(ast.parse('pass'), indent=4))
Module(
body=[
Pass()])
class ast.TypeAlias(name, type_params, value)
type 문을 통해 만들어진 타입 별칭. name은 별칭의 이름, type_params는 타입 매개변수 리스트, value는 타입 별칭의 값이에요.
>>> print(ast.dump(ast.parse('type Alias = int'), indent=4))
Module(
body=[
TypeAlias(
name=Name(id='Alias', ctx=Store()),
value=Name(id='int', ctx=Load()))])
3.12 버전에서 추가.
함수나 루프 안에서만 적용되는 다른 명령문들은 다른 섹션에서 설명돼요.
임포트 (Imports)
class ast.Import(names)
import 명령문. names는 alias 노드의 리스트예요.
>>> print(ast.dump(ast.parse('import x,y,z'), indent=4))
Module(
body=[
Import(
names=[
alias(name='x'),
alias(name='y'),
alias(name='z')])])
class ast.ImportFrom(module, names, level)
from x import y를 나타내요. module은 앞의 점 없이 'from' 이름의 원시 문자열, 또는 from . import foo 같은 명령문의 경우 None이에요. level은 상대 임포트의 수준을 담는 정수(0은 절대 임포트)예요.
>>> print(ast.dump(ast.parse('from y import x,y,z'), indent=4))
Module(
body=[
ImportFrom(
module='y',
names=[
alias(name='x'),
alias(name='y'),
alias(name='z')],
level=0)])
class ast.alias(name, asname)
두 매개변수 모두 이름의 원시 문자열이에요. asname은 일반 이름을 사용할 경우 None일 수 있어요.
>>> print(ast.dump(ast.parse('from ..foo.bar import a as b, c'), indent=4))
Module(
body=[
ImportFrom(
module='foo.bar',
names=[
alias(name='a', asname='b'),
alias(name='c')],
level=2)])
제어 흐름 (Control flow)
참고:
else같은 선택 절은 존재하지 않으면 빈 리스트로 저장돼요.
class ast.If(test, body, orelse)
if 명령문. test는 Compare 노드 같은 단일 노드를 담아요. body와 orelse는 각각 노드 리스트를 담아요. elif 절은 AST에서 특별한 표현이 없고, 이전 If의 orelse 섹션 안에 추가 If 노드로 나타나요.
>>> print(ast.dump(ast.parse("""
... if x:
... ...
... elif y:
... ...
... else:
... ...
... """), indent=4))
Module(
body=[
If(
test=Name(id='x', ctx=Load()),
body=[
Expr(
value=Constant(value=Ellipsis))],
orelse=[
If(
test=Name(id='y', ctx=Load()),
body=[
Expr(
value=Constant(value=Ellipsis))],
orelse=[
Expr(
value=Constant(value=Ellipsis))])])])
class ast.For(target, iter, body, orelse, type_comment)
for 루프. target은 루프가 할당하는 변수(들)를 단일 Name, Tuple, List, Attribute 또는 Subscript 노드로 담아요. iter는 루프할 항목을 또 단일 노드로 담아요. body와 orelse는 실행할 노드 리스트를 담아요. orelse의 것들은 루프가 break 문이 아니라 정상적으로 끝나면 실행돼요.
type_comment— 타입 애너테이션을 주석으로 담은 선택적 문자열.
>>> print(ast.dump(ast.parse("""
... for x in y:
... ...
... else:
... ...
... """), indent=4))
Module(
body=[
For(
target=Name(id='x', ctx=Store()),
iter=Name(id='y', ctx=Load()),
body=[
Expr(
value=Constant(value=Ellipsis))],
orelse=[
Expr(
value=Constant(value=Ellipsis))])])
class ast.While(test, body, orelse)
while 루프. test는 Compare 노드 같은 조건을 담아요.
>>> print(ast.dump(ast.parse("""
... while x:
... ...
... else:
... ...
... """), indent=4))
Module(
body=[
While(
test=Name(id='x', ctx=Load()),
body=[
Expr(
value=Constant(value=Ellipsis))],
orelse=[
Expr(
value=Constant(value=Ellipsis))])])
class ast.Break / class ast.Continue
break와 continue 명령문.
>>> print(ast.dump(ast.parse("""\
... for a in b:
... if a > 5:
... break
... else:
... continue
...
... """), indent=4))
Module(
body=[
For(
target=Name(id='a', ctx=Store()),
iter=Name(id='b', ctx=Load()),
body=[
If(
test=Compare(
left=Name(id='a', ctx=Load()),
ops=[
Gt()],
comparators=[
Constant(value=5)]),
body=[
Break()],
orelse=[
Continue()])])])
class ast.Try(body, handlers, orelse, finalbody)
try 블록. handlers가 ExceptHandler 노드의 리스트인 것을 제외하고 모든 속성은 실행할 노드 리스트예요.
>>> print(ast.dump(ast.parse("""
... try:
... ...
... except Exception:
... ...
... except OtherException as e:
... ...
... else:
... ...
... finally:
... ...
... """), indent=4))
Module(
body=[
Try(
body=[
Expr(
value=Constant(value=Ellipsis))],
handlers=[
ExceptHandler(
type=Name(id='Exception', ctx=Load()),
body=[
Expr(
value=Constant(value=Ellipsis))]),
ExceptHandler(
type=Name(id='OtherException', ctx=Load()),
name='e',
body=[
Expr(
value=Constant(value=Ellipsis))])],
orelse=[
Expr(
value=Constant(value=Ellipsis))],
finalbody=[
Expr(
value=Constant(value=Ellipsis))])])
class ast.TryStar(body, handlers, orelse, finalbody)
except* 절이 뒤따르는 try 블록. 속성은 Try와 같지만 handlers의 ExceptHandler 노드는 except가 아니라 except* 블록으로 해석돼요.
>>> print(ast.dump(ast.parse("""
... try:
... ...
... except* Exception:
... ...
... """), indent=4))
Module(
body=[
TryStar(
body=[
Expr(
value=Constant(value=Ellipsis))],
handlers=[
ExceptHandler(
type=Name(id='Exception', ctx=Load()),
body=[
Expr(
value=Constant(value=Ellipsis))])])])
3.11 버전에서 추가.
class ast.ExceptHandler(type, name, body)
단일 except 절. type은 일치시킬 예외 타입으로, 보통 Name 노드(또는 전체 잡기 except: 절에 대해 None)예요. name은 예외를 담을 이름의 원시 문자열, 또는 절에 as foo가 없으면 None이에요. body는 노드 리스트예요.
>>> print(ast.dump(ast.parse("""\
... try:
... a + 1
... except TypeError:
... pass
... """), indent=4))
Module(
body=[
Try(
body=[
Expr(
value=BinOp(
left=Name(id='a', ctx=Load()),
op=Add(),
right=Constant(value=1)))],
handlers=[
ExceptHandler(
type=Name(id='TypeError', ctx=Load()),
body=[
Pass()])])])
class ast.With(items, body, type_comment)
with 블록. items는 컨텍스트 관리자를 나타내는 withitem 노드의 리스트이고, body는 컨텍스트 안의 들여쓰기된 블록이에요.
type_comment— 타입 애너테이션을 주석으로 담은 선택적 문자열.
class ast.withitem(context_expr, optional_vars)
with 블록의 단일 컨텍스트 관리자. context_expr는 보통 Call 노드인 컨텍스트 관리자예요. optional_vars는 as foo 부분의 Name, Tuple 또는 List, 또는 그것이 사용되지 않으면 None이에요.
>>> print(ast.dump(ast.parse("""\
... with a as b, c as d:
... something(b, d)
... """), indent=4))
Module(
body=[
With(
items=[
withitem(
context_expr=Name(id='a', ctx=Load()),
optional_vars=Name(id='b', ctx=Store())),
withitem(
context_expr=Name(id='c', ctx=Load()),
optional_vars=Name(id='d', ctx=Store()))],
body=[
Expr(
value=Call(
func=Name(id='something', ctx=Load()),
args=[
Name(id='b', ctx=Load()),
Name(id='d', ctx=Load())]))])])
패턴 매칭 (Pattern matching)
class ast.Match(subject, cases)
match 명령문. subject는 매치의 대상(cases에 대해 매칭되는 객체)을 담고, cases는 서로 다른 케이스를 가진 match_case 노드의 iterable을 담아요. 3.10 버전에서 추가.
class ast.match_case(pattern, guard, body)
match 명령문의 단일 케이스 패턴. pattern은 대상이 매칭될 매치 패턴을 담아요. 패턴을 위해 생성된 AST 노드는 같은 문법을 공유해도 표현식을 위해 생성된 것과 다르다는 점을 참고하세요. guard 속성은 패턴이 대상과 일치하면 평가될 표현식을 담아요. body는 패턴이 일치하고 guard 표현식 평가 결과가 참이면 실행할 노드 리스트를 담아요.
>>> print(ast.dump(ast.parse("""
... match x:
... case [x] if x>0:
... ...
... case tuple():
... ...
... """), indent=4))
Module(
body=[
Match(
subject=Name(id='x', ctx=Load()),
cases=[
match_case(
pattern=MatchSequence(
patterns=[
MatchAs(name='x')]),
guard=Compare(
left=Name(id='x', ctx=Load()),
ops=[
Gt()],
comparators=[
Constant(value=0)]),
body=[
Expr(
value=Constant(value=Ellipsis))]),
match_case(
pattern=MatchClass(
cls=Name(id='tuple', ctx=Load())),
body=[
Expr(
value=Constant(value=Ellipsis))])])])
3.10 버전에서 추가.
class ast.MatchValue(value)
동등성으로 비교하는 매치 리터럴 또는 값 패턴. value는 표현식 노드예요. 허용되는 값 노드는 match 명령문 문서에 설명된 대로 제한돼요. 이 패턴은 매치 대상이 평가된 값과 같으면 성공해요.
>>> print(ast.dump(ast.parse("""
... match x:
... case "Relevant":
... ...
... """), indent=4))
Module(
body=[
Match(
subject=Name(id='x', ctx=Load()),
cases=[
match_case(
pattern=MatchValue(
value=Constant(value='Relevant')),
body=[
Expr(
value=Constant(value=Ellipsis))])])])
3.10 버전에서 추가.
class ast.MatchSingleton(value)
정체성으로 비교하는 매치 리터럴 패턴. value는 비교할 싱글턴(None, True, False)이에요. 이 패턴은 매치 대상이 주어진 상수이면 성공해요.
>>> print(ast.dump(ast.parse("""
... match x:
... case None:
... ...
... """), indent=4))
Module(
body=[
Match(
subject=Name(id='x', ctx=Load()),
cases=[
match_case(
pattern=MatchSingleton(value=None),
body=[
Expr(
value=Constant(value=Ellipsis))])])])
3.10 버전에서 추가.
class ast.MatchSequence(patterns)
매치 시퀀스 패턴. patterns는 대상이 시퀀스일 때 대상 요소에 대해 매칭될 패턴을 담아요. 하위 패턴 중 하나가 MatchStar 노드이면 가변 길이 시퀀스와 일치하고, 그렇지 않으면 고정 길이 시퀀스와 일치해요.
>>> print(ast.dump(ast.parse("""
... match x:
... case [1, 2]:
... ...
... """), indent=4))
Module(
body=[
Match(
subject=Name(id='x', ctx=Load()),
cases=[
match_case(
pattern=MatchSequence(
patterns=[
MatchValue(
value=Constant(value=1)),
MatchValue(
value=Constant(value=2))]),
body=[
Expr(
value=Constant(value=Ellipsis))])])])
3.10 버전에서 추가.
class ast.MatchStar(name)
가변 길이 매치 시퀀스 패턴에서 시퀀스의 나머지를 일치시켜요. name이 None이 아니면, 전체 시퀀스 패턴이 성공할 때 나머지 시퀀스 요소를 담은 리스트가 그 이름에 바인딩돼요.
>>> print(ast.dump(ast.parse("""
... match x:
... case [1, 2, *rest]:
... ...
... case [*_]:
... ...
... """), indent=4))
Module(
body=[
Match(
subject=Name(id='x', ctx=Load()),
cases=[
match_case(
pattern=MatchSequence(
patterns=[
MatchValue(
value=Constant(value=1)),
MatchValue(
value=Constant(value=2)),
MatchStar(name='rest')]),
body=[
Expr(
value=Constant(value=Ellipsis))]),
match_case(
pattern=MatchSequence(
patterns=[
MatchStar()]),
body=[
Expr(
value=Constant(value=Ellipsis))])])])
3.10 버전에서 추가.
class ast.MatchMapping(keys, patterns, rest)
매치 매핑 패턴. keys는 표현식 노드의 시퀀스예요. patterns는 대응하는 패턴 노드의 시퀀스예요. rest는 나머지 매핑 요소를 캡처하기 위해 지정할 수 있는 선택적 이름이에요. 허용되는 키 표현식은 match 명령문 문서에 설명된 대로 제한돼요.
이 패턴은 대상이 매핑이고, 평가된 모든 키 표현식이 매핑에 존재하며, 각 키에 대응하는 값이 대응하는 하위 패턴과 일치하면 성공해요. rest가 None이 아니면, 전체 매핑 패턴이 성공할 때 나머지 매핑 요소를 담은 dict가 그 이름에 바인딩돼요.
>>> print(ast.dump(ast.parse("""
... match x:
... case {1: _, 2: _}:
... ...
... case {**rest}:
... ...
... """), indent=4))
Module(
body=[
Match(
subject=Name(id='x', ctx=Load()),
cases=[
match_case(
pattern=MatchMapping(
keys=[
Constant(value=1),
Constant(value=2)],
patterns=[
MatchAs(),
MatchAs()]),
body=[
Expr(
value=Constant(value=Ellipsis))]),
match_case(
pattern=MatchMapping(rest='rest'),
body=[
Expr(
value=Constant(value=Ellipsis))])])])
3.10 버전에서 추가.
class ast.MatchClass(cls, patterns, kwd_attrs, kwd_patterns)
매치 클래스 패턴. cls는 매칭할 명목상 클래스를 주는 표현식이에요. patterns는 클래스가 정의한 시퀀스의 패턴 매칭 속성에 대해 매칭될 패턴 노드의 시퀀스예요. kwd_attrs는 매칭할 추가 속성의 시퀀스(클래스 패턴에서 키워드 인자로 지정), kwd_patterns는 대응하는 패턴(클래스 패턴에서 키워드 값으로 지정)이에요.
이 패턴은 대상이 지정된 클래스의 인스턴스이고, 모든 위치 패턴이 대응하는 클래스 정의 속성과 일치하며, 지정된 모든 키워드 속성이 대응하는 패턴과 일치하면 성공해요. 클래스는 매칭 중인 인스턴스에 대해 패턴 노드를 일치시키기 위해 self를 반환하는 프로퍼티를 정의할 수 있어요. 여러 내장 타입도 match 명령문 문서에 설명된 대로 그런 방식으로 일치돼요.
>>> print(ast.dump(ast.parse("""
... match x:
... case Point2D(0, 0):
... ...
... case Point3D(x=0, y=0, z=0):
... ...
... """), indent=4))
Module(
body=[
Match(
subject=Name(id='x', ctx=Load()),
cases=[
match_case(
pattern=MatchClass(
cls=Name(id='Point2D', ctx=Load()),
patterns=[
MatchValue(
value=Constant(value=0)),
MatchValue(
value=Constant(value=0))]),
body=[
Expr(
value=Constant(value=Ellipsis))]),
match_case(
pattern=MatchClass(
cls=Name(id='Point3D', ctx=Load()),
kwd_attrs=[
'x',
'y',
'z'],
kwd_patterns=[
MatchValue(
value=Constant(value=0)),
MatchValue(
value=Constant(value=0)),
MatchValue(
value=Constant(value=0))]),
body=[
Expr(
value=Constant(value=Ellipsis))])])])
3.10 버전에서 추가.
class ast.MatchAs(pattern, name)
매치 "as-pattern", 캡처 패턴 또는 와일드카드 패턴. pattern은 대상이 매칭될 매치 패턴을 담아요. pattern이 None이면 노드는 캡처 패턴(즉 맨 이름)을 나타내고 항상 성공해요. name 속성은 패턴이 성공하면 바인딩될 이름을 담아요. name이 None이면 pattern도 None이어야 하고 노드는 와일드카드 패턴을 나타내요.
>>> print(ast.dump(ast.parse("""
... match x:
... case [x] as y:
... ...
... case _:
... ...
... """), indent=4))
Module(
body=[
Match(
subject=Name(id='x', ctx=Load()),
cases=[
match_case(
pattern=MatchAs(
pattern=MatchSequence(
patterns=[
MatchAs(name='x')]),
name='y'),
body=[
Expr(
value=Constant(value=Ellipsis))]),
match_case(
pattern=MatchAs(),
body=[
Expr(
value=Constant(value=Ellipsis))])])])
3.10 버전에서 추가.
class ast.MatchOr(patterns)
매치 "or-pattern". or-pattern은 하위 패턴 각각을 대상에 차례로 매칭해 하나가 성공할 때까지 시도해요. 그러면 or-pattern이 성공한 것으로 간주돼요. 하위 패턴 중 어느 것도 성공하지 않으면 or-pattern은 실패해요. patterns 속성은 대상에 매칭될 매치 패턴 노드의 리스트를 담아요.
>>> print(ast.dump(ast.parse("""
... match x:
... case [x] | (y):
... ...
... """), indent=4))
Module(
body=[
Match(
subject=Name(id='x', ctx=Load()),
cases=[
match_case(
pattern=MatchOr(
patterns=[
MatchSequence(
patterns=[
MatchAs(name='x')]),
MatchAs(name='y')]),
body=[
Expr(
value=Constant(value=Ellipsis))])])])
3.10 버전에서 추가.
타입 애너테이션 (Type annotations)
class ast.TypeIgnore(lineno, tag)
lineno에 위치한 # type: ignore 주석. tag는 # 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노드는type_comments매개변수가False(기본값)로 설정되면 생성되지 않아요. 자세한 내용은ast.parse()를 참고하세요.3.8 버전에서 추가.
타입 매개변수 (Type parameters)
타입 매개변수는 클래스, 함수, 타입 별칭에 존재할 수 있어요.
class ast.TypeVar(name, bound, default_value)
typing.TypeVar. name은 타입 변수의 이름이에요. bound는 있으면 바운드 또는 제약이에요. bound가 Tuple이면 제약을 나타내고, 그렇지 않으면 바운드를 나타내요. default_value는 기본값이에요. TypeVar에 기본값이 없으면 이 속성은 None으로 설정돼요.
>>> print(ast.dump(ast.parse("type Alias[T: int = bool] = list[T]"), indent=4))
Module(
body=[
TypeAlias(
name=Name(id='Alias', ctx=Store()),
type_params=[
TypeVar(
name='T',
bound=Name(id='int', ctx=Load()),
default_value=Name(id='bool', ctx=Load()))],
value=Subscript(
value=Name(id='list', ctx=Load()),
slice=Name(id='T', ctx=Load()),
ctx=Load()))])
3.12 버전에서 추가. 3.13 버전 변경: default_value 매개변수 추가.
class ast.ParamSpec(name, default_value)
typing.ParamSpec. name은 매개변수 사양의 이름이에요. default_value는 기본값이에요. ParamSpec에 기본값이 없으면 이 속성은 None으로 설정돼요.
>>> print(ast.dump(ast.parse("type Alias[**P = [int, str]] = Callable[P, int]"), indent=4))
Module(
body=[
TypeAlias(
name=Name(id='Alias', ctx=Store()),
type_params=[
ParamSpec(
name='P',
default_value=List(
elts=[
Name(id='int', ctx=Load()),
Name(id='str', ctx=Load())],
ctx=Load()))],
value=Subscript(
value=Name(id='Callable', ctx=Load()),
slice=Tuple(
elts=[
Name(id='P', ctx=Load()),
Name(id='int', ctx=Load())],
ctx=Load()),
ctx=Load()))])
3.12 버전에서 추가. 3.13 버전 변경: default_value 매개변수 추가.
class ast.TypeVarTuple(name, default_value)
typing.TypeVarTuple. name은 타입 변수 튜플의 이름이에요. default_value는 기본값이에요. TypeVarTuple에 기본값이 없으면 이 속성은 None으로 설정돼요.
>>> print(ast.dump(ast.parse("type Alias[*Ts = ()] = tuple[*Ts]"), indent=4))
Module(
body=[
TypeAlias(
name=Name(id='Alias', ctx=Store()),
type_params=[
TypeVarTuple(
name='Ts',
default_value=Tuple(ctx=Load()))],
value=Subscript(
value=Name(id='tuple', ctx=Load()),
slice=Tuple(
elts=[
Starred(
value=Name(id='Ts', ctx=Load()),
ctx=Load())],
ctx=Load()),
ctx=Load()))])
3.12 버전에서 추가. 3.13 버전 변경: default_value 매개변수 추가.
함수와 클래스 정의 (Function and class definitions)
class ast.FunctionDef(name, args, body, decorator_list, returns, type_comment, type_params)
함수 정의. name은 함수 이름의 원시 문자열이에요. args는 arguments 노드예요. body는 함수 안의 노드 리스트예요. decorator_list는 적용할 데코레이터의 리스트로, 가장 바깥쪽이 먼저 저장돼요(즉 리스트의 첫 번째가 마지막에 적용돼요). returns는 반환 애너테이션이에요. type_params는 타입 매개변수 리스트예요.
type_comment— 타입 애너테이션을 주석으로 담은 선택적 문자열.
3.12 버전 변경:
type_params추가.
class ast.Lambda(args, body)
lambda는 표현식 안에서 사용될 수 있는 최소 함수 정의예요. FunctionDef와 달리 body는 단일 노드를 담아요.
>>> print(ast.dump(ast.parse('lambda x,y: ...'), indent=4))
Module(
body=[
Expr(
value=Lambda(
args=arguments(
args=[
arg(arg='x'),
arg(arg='y')]),
body=Constant(value=Ellipsis)))])
class ast.arguments(posonlyargs, args, vararg, kwonlyargs, kw_defaults, kwarg, defaults)
함수의 인자. posonlyargs, args, kwonlyargs는 arg 노드 리스트예요. vararg와 kwarg는 *args, **kwargs 매개변수를 가리키는 단일 arg 노드예요. kw_defaults는 키워드 전용 인자의 기본값 리스트예요. 하나가 None이면 대응하는 인자는 필수예요. defaults는 위치로 전달될 수 있는 인자의 기본값 리스트예요. 기본값이 더 적으면 마지막 n개 인자에 대응해요.
class ast.arg(arg, annotation, type_comment)
리스트의 단일 인자. arg는 인자 이름의 원시 문자열이고, annotation은 Name 노드 같은 그 애너테이션이에요.
type_comment— 타입 애너테이션을 주석으로 담은 선택적 문자열.
>>> print(ast.dump(ast.parse("""\
... @decorator1
... @decorator2
... def f(a: 'annotation', b=1, c=2, *d, e, f=3, **g) -> 'return annotation':
... pass
... """), indent=4))
Module(
body=[
FunctionDef(
name='f',
args=arguments(
args=[
arg(
arg='a',
annotation=Constant(value='annotation')),
arg(arg='b'),
arg(arg='c')],
vararg=arg(arg='d'),
kwonlyargs=[
arg(arg='e'),
arg(arg='f')],
kw_defaults=[
None,
Constant(value=3)],
kwarg=arg(arg='g'),
defaults=[
Constant(value=1),
Constant(value=2)]),
body=[
Pass()],
decorator_list=[
Name(id='decorator1', ctx=Load()),
Name(id='decorator2', ctx=Load())],
returns=Constant(value='return annotation'))])
class ast.Return(value)
return 명령문.
>>> print(ast.dump(ast.parse('return 4'), indent=4))
Module(
body=[
Return(
value=Constant(value=4))])
class ast.Yield(value) / class ast.YieldFrom(value)
yield 또는 yield from 표현식. 이것들은 표현식이므로, 보내진 값이 사용되지 않으면 Expr 노드로 감싸져야 해요.
>>> print(ast.dump(ast.parse('yield x'), indent=4))
Module(
body=[
Expr(
value=Yield(
value=Name(id='x', ctx=Load()))])
>>> print(ast.dump(ast.parse('yield from x'), indent=4))
Module(
body=[
Expr(
value=YieldFrom(
value=Name(id='x', ctx=Load()))])
class ast.Global(names) / class ast.Nonlocal(names)
global과 nonlocal 명령문. names는 원시 문자열의 리스트예요.
>>> print(ast.dump(ast.parse('global x,y,z'), indent=4))
Module(
body=[
Global(
names=[
'x',
'y',
'z'])])
>>> print(ast.dump(ast.parse('nonlocal x,y,z'), indent=4))
Module(
body=[
Nonlocal(
names=[
'x',
'y',
'z'])])
class ast.ClassDef(name, bases, keywords, body, decorator_list, type_params)
클래스 정의. name은 클래스 이름의 원시 문자열이에요. bases는 명시적으로 지정된 기반 클래스의 노드 리스트예요. keywords는 주로 'metaclass'를 위한 keyword 노드 리스트예요. PEP 3115에 따라 다른 키워드는 메타클래스로 전달돼요. body는 클래스 정의 안의 코드를 나타내는 노드 리스트예요. decorator_list는 FunctionDef에서처럼 노드 리스트예요. type_params는 타입 매개변수 리스트예요.
>>> print(ast.dump(ast.parse("""\
... @decorator1
... @decorator2
... class Foo(base1, base2, metaclass=meta):
... pass
... """), indent=4))
Module(
body=[
ClassDef(
name='Foo',
bases=[
Name(id='base1', ctx=Load()),
Name(id='base2', ctx=Load())],
keywords=[
keyword(
arg='metaclass',
value=Name(id='meta', ctx=Load()))],
body=[
Pass()],
decorator_list=[
Name(id='decorator1', ctx=Load()),
Name(id='decorator2', ctx=Load())])])
3.12 버전 변경: type_params 추가.
Async와 await
class ast.AsyncFunctionDef(name, args, body, decorator_list, returns, type_comment, type_params)
async def 함수 정의. FunctionDef와 같은 필드를 가져요. 3.12 버전 변경: type_params 추가.
class ast.Await(value)
await 표현식. value는 기다리는 것이에요. AsyncFunctionDef의 본문에서만 유효해요.
>>> print(ast.dump(ast.parse("""\
... async def f():
... await other_func()
... """), indent=4))
Module(
body=[
AsyncFunctionDef(
name='f',
args=arguments(),
body=[
Expr(
value=Await(
value=Call(
func=Name(id='other_func', ctx=Load()))))])])
class ast.AsyncFor(target, iter, body, orelse, type_comment) / class ast.AsyncWith(items, body, type_comment)
async for 루프와 async with 컨텍스트 관리자. 각각 For와 With와 같은 필드를 가져요. AsyncFunctionDef의 본문에서만 유효해요.
참고:
ast.parse()로 문자열을 파싱할 때, 반환된 트리의 연산자 노드(ast.operator,ast.unaryop,ast.cmpop,ast.boolop,ast.expr_context의 서브클래스)는 싱글턴이 돼요. 하나를 변경하면 같은 값의 다른 모든 출현(예:ast.Add)에도 반영돼요.
ast 헬퍼 (ast helpers)
노드 클래스 외에도 ast 모듈은 추상 구문 트리를 탐색하기 위한 다음 유틸리티 함수와 클래스를 정의해요:
ast.parse(source, filename='unknown', mode='exec', *, type_comments=False, feature_version=None, optimize=-1)
소스를 AST 노드로 파싱해요. 이는 compile(source, filename, mode, flags=FLAGS_VALUE, optimize=optimize)와 동일한데, FLAGS_VALUE는 optimize = 0이면 ast.PyCF_ONLY_AST이고 그렇지 않으면 ast.PyCF_OPTIMIZED_AST예요.
type_comments=True가 주어지면 파서가 PEP 484와 PEP 526이 지정한 대로 타입 주석을 검사하고 반환하도록 수정돼요. 이는 compile()에 전달된 플래그에 ast.PyCF_TYPE_COMMENTS를 추가하는 것과 동일해요. 이것은 잘못 배치된 타입 주석에 대해 문법 오류를 보고해요. 이 플래그가 없으면 타입 주석은 무시되고 선택된 AST 노드의 type_comment 필드는 항상 None이 돼요. 게다가 # type: ignore 주석의 위치는 Module의 type_ignores 속성으로 반환돼요(그렇지 않으면 항상 빈 리스트).
또한 mode가 'func_type'이면 입력 문법이 PEP 484 "시그니처 타입 주석", 예를 들어 (str, int) -> List[str]에 대응하도록 수정돼요.
feature_version을 튜플 (major, minor)로 설정하면 그 Python 버전의 문법으로 파싱하려는 "최선의 노력(best-effort)" 시도를 해요. 예를 들어 feature_version=(3, 9)를 설정하면 match 문의 파싱을 허용하지 않으려 시도해요. 현재 major는 3과 같아야 해요. 가장 낮은 지원 버전은 (3, 7)이고(그리고 이건 미래의 Python 버전에서 높아질 수도 있어요), 가장 높은 것은 sys.version_info[0:2]예요. "최선의 노력" 시도는 파싱(또는 파싱 성공)이 feature_version에 해당하는 Python 버전에서 실행될 때와 같다는 보장이 없다는 뜻이에요.
source에 null 문자(\0)가 포함되면 ValueError가 발생해요.
경고: 소스를 AST 객체로 성공적으로 파싱한다고 해서 제공된 소스 코드가 실행 가능한 유효한 Python 코드라는 보장은 아니에요. 컴파일 단계가 추가
SyntaxError예외를 발생시킬 수 있기 때문이에요. 예를 들어 소스return 42는 return 문에 대한 유효한 AST 노드를 생성하지만 단독으로 컴파일될 수는 없어요(함수 노드 안에 있어야 함). 특히ast.parse()는 컴파일 단계가 하는 스코핑 검사를 하지 않아요.경고: Python의 AST 컴파일러의 스택 깊이 제한 때문에 충분히 크거나 복잡한 문자열로 Python 인터프리터를 크래시시키는 것이 가능해요.
3.8 버전 변경:
type_comments,mode='func_type',feature_version추가.3.13 버전 변경:
feature_version의 최소 지원 버전이 이제(3, 7)이에요.optimize인자가 추가됐어요.
ast.unparse(ast_obj)
ast.AST 객체를 언파싱하고, 다시 ast.parse()로 파싱하면 동등한 ast.AST 객체를 생성할 코드가 담긴 문자열을 생성해요.
경고: 생성된 코드 문자열이 원래
ast.AST객체를 생성한 원본 코드와 반드시 같을 필요는 없어요(상수 튜플/frozenset 같은 컴파일러 최적화 없이).경고: 매우 복잡한 표현식을 언파싱하려 하면
RecursionError가 발생해요.3.9 버전에서 추가.
ast.literal_eval(node_or_string)
표현식 노드 또는 Python 리터럴이나 컨테이너 표시만 포함한 문자열을 평가해요. 제공된 문자열 또는 노드는 다음 Python 리터럴 구조만으로 구성될 수 있어요: 문자열, bytes, 숫자, 튜플, 리스트, dict, 집합, 불리언, None, Ellipsis. 이는 값을 직접 파싱할 필요 없이 Python 값을 포함한 문자열을 평가하는 데 사용될 수 있어요. 연산자나 인덱싱을 포함하는 임의로 복잡한 표현식은 평가할 수 없어요.
이 함수는 과거에 그 의미를 정의하지 않고 "안전(safe)"하다고 문서화됐어요. 그것은 오해를 불러일으키는 것이었어요. 이것은 더 일반적인 eval()과 달리 Python 코드를 실행하지 않도록 특별히 설계됐어요. 네임스페이스도, 이름 조회도, 밖으로 호출할 능력도 없어요. 하지만 공격으로부터 자유롭지는 않아요. 비교적 작은 입력이 메모리 고갈이나 C 스택 고갈로 이어져 프로세스를 크래시시킬 수 있어요. 일부 입력에서는 과도한 CPU 소비의 서비스 거부 가능성도 있어요. 따라서 신뢰할 수 없는 데이터에 호출하는 것은 권장되지 않아요.
경고: Python의 AST 컴파일러의 스택 깊이 제한 때문에 Python 인터프리터를 크래시시키는 것이 가능해요.
잘못된 입력에 따라
ValueError,TypeError,SyntaxError,MemoryError,RecursionError를 발생시킬 수 있어요.3.2 버전 변경: 이제 bytes와 set 리터럴을 허용해요.
3.9 버전 변경: 이제
'set()'으로 빈 집합을 만드는 것을 지원해요.3.10 버전 변경: 문자열 입력의 경우 앞의 공백과 탭이 이제 제거돼요.
ast.get_docstring(node, clean=True)
주어진 노드(FunctionDef, AsyncFunctionDef, ClassDef, 또는 Module 노드여야 함)의 docstring을 반환하거나, docstring이 없으면 None을 반환해요. clean이 참이면 inspect.cleandoc()으로 docstring의 들여쓰기를 정리해요. 3.5 버전 변경: AsyncFunctionDef 지원.
ast.get_source_segment(source, node, *, padded=False)
node를 생성한 소스의 소스 코드 세그먼트를 가져와요. 일부 위치 정보(lineno, end_lineno, col_offset, end_col_offset)가 없으면 None을 반환해요. padded가 True면 여러 줄 명령문의 첫 줄은 원래 위치와 일치하도록 공백으로 패딩돼요. 3.8 버전에서 추가.
ast.fix_missing_locations(node)
compile()로 노드 트리를 컴파일할 때 컴파일러는 그것을 지원하는 모든 노드에 lineno와 col_offset 속성을 기대해요. 생성된 노드에는 이것을 채우기가 꽤 지루하므로, 이 헬퍼는 아직 설정되지 않은 곳에 부모 노드의 값을 설정함으로써 재귀적으로 이 속성을 추가해요. node에서 시작해 재귀적으로 동작해요.
ast.increment_lineno(node, n=1)
node에서 시작하는 트리의 각 노드의 줄 번호와 끝 줄 번호를 n만큼 증가시켜요. 파일의 다른 위치로 코드를 "이동"하는 데 유용해요.
ast.copy_location(new_node, old_node)
가능하면 old_node에서 new_node로 소스 위치(lineno, col_offset, end_lineno, end_col_offset)를 복사하고 new_node를 반환해요.
ast.iter_fields(node)
node._fields에 존재하는 각 필드에 대해 (fieldname, value) 튜플을 yield해요.
ast.iter_child_nodes(node)
node의 모든 직접 자식 노드를 yield해요. 즉, 노드인 모든 필드와 노드 리스트인 필드의 모든 항목이에요.
ast.walk(node)
node에서 시작하는 트리의 모든 하위 노드(node 자체 포함)를 지정된 순서 없이 재귀적으로 yield해요. 노드를 제자리에서만 수정하고 컨텍스트에 신경 쓰지 않을 때 유용해요.
class ast.NodeVisitor
추상 구문 트리를 탐색하고 찾은 모든 노드에 대해 방문자 함수를 호출하는 노드 방문자 베이스 클래스. 이 함수는 visit() 메서드가 전달하는 값을 반환할 수 있어요. 이 클래스는 서브클래스화되고, 서브클래스가 방문자 메서드를 추가하도록 설계됐어요.
visit(node)— 노드를 방문해요. 기본 구현은self.visit_classname(classname은 노드 클래스의 이름)이라고 불리는 메서드를 호출하거나, 그 메서드가 존재하지 않으면generic_visit()을 호출해요.generic_visit(node)— 이 방문자는 노드의 모든 자식에 대해visit()을 호출해요. 커스텀 방문자 메서드가 있는 노드의 자식 노드는 방문자가generic_visit()을 호출하거나 그 자체로 방문하지 않는 한 방문되지 않는다는 점을 참고하세요.visit_Constant(node)— 모든 상수 노드를 처리해요.
트리 탐색 중에 노드에 변경을 적용하고 싶다면 NodeVisitor를 사용하지 마세요. 이를 위해 수정을 허용하는 특별한 방문자(NodeTransformer)가 존재해요.
3.8부터 deprecated, 3.14에서 제거:
visit_Num(),visit_Str(),visit_Bytes(),visit_NameConstant(),visit_Ellipsis()메서드는 Python 3.14+에서 호출되지 않아요. 모든 상수 노드를 처리하려면visit_Constant()메서드를 추가하세요.
class ast.NodeTransformer
추상 구문 트리를 탐색하고 노드 수정을 허용하는 NodeVisitor 서브클래스. NodeTransformer는 AST를 탐색하고 방문자 메서드의 반환값을 사용해 옛 노드를 교체하거나 제거해요. 방문자 메서드의 반환값이 None이면 노드가 그 위치에서 제거되고, 그렇지 않으면 반환값으로 교체돼요. 반환값이 원래 노드일 수도 있는데, 그 경우 어떤 교체도 일어나지 않아요.
다음은 이름 조회(foo)의 모든 출현을 data['foo']로 다시 쓰는 변환기 예시예요:
class RewriteName(NodeTransformer):
def visit_Name(self, node):
return Subscript(
value=Name(id='data', ctx=Load()),
slice=Constant(value=node.id),
ctx=node.ctx
)
작동 중인 노드에 자식 노드가 있다면 자식 노드를 직접 변환하거나 먼저 그 노드에 generic_visit() 메서드를 호출해야 한다는 점을 명심하세요.
명령문 컬렉션의 일부였던 노드(모든 명령문 노드에 적용)의 경우 방문자는 단일 노드 대신 노드 리스트를 반환할 수도 있어요.
NodeTransformer가 새 노드를(원래 트리의 일부가 아니었던 것을) 위치 정보(lineno 같은)를 주지 않고 도입한다면, fix_missing_locations()을 새 하위 트리와 함께 호출해 위치 정보를 재계산해야 해요:
tree = ast.parse('foo', mode='eval')
new_tree = fix_missing_locations(RewriteName().visit(tree))
보통 변환기를 이렇게 사용해요:
node = YourTransformer().visit(node)
ast.dump(node, annotate_fields=True, include_attributes=False, *, indent=None, show_empty=False)
node의 트리를 포맷된 덤프로 반환해요. 이것은 주로 디버깅 목적으로 유용해요. annotate_fields가 참(기본값)이면 반환 문자열은 필드의 이름과 값을 보여줘요. annotate_fields가 거짓이면 결과 문자열은 모호하지 않은 필드 이름을 생략해 더 컴팩트해져요. 줄 번호와 열 오프셋 같은 속성은 기본적으로 덤프되지 않아요. 원하면 include_attributes를 참으로 설정할 수 있어요.
indent가 음이 아닌 정수 또는 문자열이면 트리가 그 들여쓰기 수준으로 예쁘게 출력돼요. 들여쓰기 수준 0, 음수, 또는 ""는 새 줄만 삽입해요. None(기본값)은 단일 줄 표현을 선택해요. 양의 정수 들여쓰기를 사용하면 수준마다 그만큼 공백으로 들여써요. indent가 문자열("\t" 같은)이면 각 수준을 들여쓰는 데 그 문자열이 사용돼요.
show_empty가 거짓(기본값)이면 선택적 빈 리스트가 출력에서 생략돼요. 선택적 None 값은 항상 생략돼요.
3.9 버전 변경:
indent옵션 추가.3.13 버전 변경:
show_empty옵션 추가.
>>> print(ast.dump(ast.parse("""\
... async def f():
... await other_func()
... """), indent=4, show_empty=True))
Module(
body=[
AsyncFunctionDef(
name='f',
args=arguments(
posonlyargs=[],
args=[],
kwonlyargs=[],
kw_defaults=[],
defaults=[]),
body=[
Expr(
value=Await(
value=Call(
func=Name(id='other_func', ctx=Load()),
args=[],
keywords=[])))],
decorator_list=[],
type_params=[])],
type_ignores=[])
ast.compare(a, b, /, *, compare_attributes=False)
두 AST를 재귀적으로 비교해요. compare_attributes는 비교에서 AST 속성이 고려되는지 여부에 영향을 줘요. compare_attributes가 False(기본값)이면 속성은 무시돼요. 그렇지 않으면 모두 같아야 해요. 이 옵션은 AST가 구조적으로 같지만 공백이나 비슷한 세부사항에서 다른지 확인하는 데 유용해요. 속성에는 줄 번호와 열 오프셋이 포함돼요. 3.14 버전에서 추가.
컴파일러 플래그 (Compiler flags)
다음 플래그는 프로그램 컴파일에 대한 효과를 바꾸기 위해 compile()에 전달될 수 있어요:
ast.PyCF_ALLOW_TOP_LEVEL_AWAIT
최상위 await, async for, async with 및 async 컴프리헨션 지원을 활성화해요. 3.8 버전에서 추가.
ast.PyCF_ONLY_AST
컴파일된 코드 객체를 반환하는 대신 추상 구문 트리를 생성하고 반환해요.
ast.PyCF_OPTIMIZED_AST
반환된 AST가 compile()이나 ast.parse()의 optimize 인자에 따라 최적화돼요. 3.13 버전에서 추가.
ast.PyCF_TYPE_COMMENTS
PEP 484와 PEP 526 스타일 타입 주석(# type: type, # type: ignore stuff) 지원을 활성화해요. 3.8 버전에서 추가.
커맨드라인 사용
3.9 버전에서 추가.
ast 모듈은 커맨드라인에서 스크립트로 실행될 수 있어요. 간단히:
python -m ast [-m mode] [-a] [infile]
다음 옵션이 받아들여져요:
-h, --help— 도움말 메시지를 보여주고 종료.-m mode/--mode mode—parse()의mode인자처럼 어떤 종류의 코드를 컴파일해야 하는지 지정.--no-type-comments— 타입 주석을 파싱하지 않음.-a, --include-attributes— 줄 번호와 열 오프셋 같은 속성 포함.-i indent/--indent indent— AST에서 노드의 들여쓰기(공백 수).--feature-version version—3.x형식(예:3.10)의 Python 버전. 기본값은 인터프리터의 현재 버전. 3.14 버전에서 추가.-O level/--optimize level— 파서의 최적화 수준. 기본값은 최적화 없음. 3.14 버전에서 추가.--show-empty— 빈 리스트와None인 필드 표시. 기본값은 빈 객체 표시 안 함. 3.14 버전에서 추가.
infile이 지정되면 그 내용이 AST로 파싱되고 stdout으로 덤프돼요. 그렇지 않으면 stdin에서 내용이 읽혀요.
더 알아보기
- Green Tree Snakes — Python AST 작업에 대한 좋은 상세가 있는 외부 문서 리소스.
- ASTTokens — Python AST를 생성된 소스 코드의 토큰과 텍스트 위치로 주석. 소스 코드 변환을 만드는 도구에 도움이 돼요.
- leoAst.py — 토큰과 AST 노드 사이에 양방향 링크를 삽입해 python 프로그램의 토큰 기반과 파스 트리 기반 보기를 통합.
- LibCST — ast 트리처럼 보이는 Concrete Syntax Tree로 코드를 파싱하고 모든 포맷팅 세부사항을 유지해요. 자동 리팩터링(codemod) 애플리케이션과 린터를 만드는 데 유용해요.
- Parso — 오류 복구와 여러 Python 버전(여러 Python 버전에서)의 라운드트립 파싱을 지원하는 Python 파서. Parso는 또한 파일에서 여러 문법 오류를 나열할 수 있어요.