- 8. Compound statements
복합 문에는 다른 문(그룹)이 포함됩니다. 어떤 식으로든 다른 명령문의 실행에 영향을 미치거나 제어합니다. 일반적으로 복합문은 여러 줄에 걸쳐 있지만 단순한 화신에서는 전체 복합문이 한 줄에 포함될 수 있습니다.
if, while 및 for 문은 전통적인 제어 흐름 구조를 구현합니다. try는 문 그룹에 대한 예외 처리기 및/또는 정리 코드를 지정하는 반면 with 문은 코드 블록 주위에서 초기화 및 종료 코드를 실행할 수 있도록 합니다. 함수 및 클래스 정의도 구문적으로 복합 명령문입니다.
복합문은 하나 이상의 ‘절’로 구성됩니다. 절은 헤더와 ‘스위트’로 구성됩니다. 특정 복합문의 절 헤더는 모두 동일한 들여쓰기 수준에 있습니다. 각 절 헤더는 고유하게 식별되는 키워드로 시작하고 콜론으로 끝납니다. 스위트는 절에 의해 제어되는 명령문 그룹입니다. 스위트는 헤더 콜론 다음의 헤더와 같은 줄에 있는 하나 이상의 세미콜론으로 구분된 간단한 문이거나 후속 줄에 있는 하나 이상의 들여쓰기된 문일 수 있습니다. 스위트의 후자 형식만이 중첩된 복합 명령문을 포함할 수 있습니다. 다음은 위법입니다. 주로 다음 else 절이 어떤 if 절에 속하는지 명확하지 않기 때문입니다.
if test1: if test2: print(x)
또한 세미콜론은 이 컨텍스트에서 콜론보다 더 밀접하게 바인딩되므로 다음 예제에서는 print() 호출이 모두 실행되거나 전혀 실행되지 않습니다.
if x < y < z: print(x); print(y); print(z)
요약:
compound_stmt ::= if_stmt
| while_stmt
| for_stmt
| try_stmt
| with_stmt
| match_stmt
| funcdef
| classdef
| async_with_stmt
| async_for_stmt
| async_funcdef
suite ::= stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT
statement ::= stmt_list NEWLINE | compound_stmt
stmt_list ::= simple_stmt (";" simple_stmt)* [";"]
명령문은 항상 NEWLINE으로 끝나고 그 뒤에 DEDENT가 올 수 있음에 유의하십시오. 또한 선택적 연속 절은 항상 명령문을 시작할 수 없는 키워드로 시작하므로 모호성이 없습니다(파이썬에서 ‘dangling else’ 문제는 중첩된 if 문을 들여쓰도록 요구하여 해결됨).
다음 섹션의 문법 규칙 형식은 명확성을 위해 각 절을 별도의 줄에 배치합니다.
8.1. The if
statement
if 문은 조건부 실행에 사용됩니다.
if_stmt ::= "if" assignment_expression ":" suite
("elif" assignment_expression ":" suite)*
["else" ":" suite]
참이 될 때까지 표현식을 하나씩 평가하여 스위트 중 정확히 하나를 선택합니다(참과 거짓의 정의에 대한 부울 연산 섹션 참조). 그런 다음 해당 제품군이 실행됩니다(그리고 if 문의 다른 부분은 실행되거나 평가되지 않습니다). 모든 식이 거짓이면 else 절의 모음(있는 경우)이 실행됩니다.
8.2. The while
statement
while 문은 표현식이 참인 동안 반복 실행에 사용됩니다.
while_stmt ::= "while" assignment_expression ":" suite
["else" ":" suite]
이것은 표현식을 반복적으로 테스트하고 참이면 첫 번째 스위트를 실행합니다. 표현식이 거짓이면(첫 번째 테스트일 수 있음) else 절의 스위트(존재하는 경우)가 실행되고 루프가 종료됩니다.
첫 번째 모음에서 실행되는 break 문은 else 절의 모음을 실행하지 않고 루프를 종료합니다. 첫 번째 스위트에서 실행되는 continue 문은 나머지 스위트를 건너뛰고 표현식 테스트로 돌아갑니다.
8.3. The for
statement
for 문은 시퀀스(예: 문자열, 튜플 또는 목록) 또는 기타 반복 가능한 객체의 요소를 반복하는 데 사용됩니다.
for_stmt ::= "for" target_list "in" starred_list ":" suite
["else" ":" suite]
stard_list 표현식은 한 번 평가됩니다. iterable 객체를 생성해야 합니다. 해당 iterable에 대해 iterator가 생성됩니다. 반복자가 제공한 첫 번째 항목은 할당에 대한 표준 규칙(할당문 참조)을 사용하여 대상 목록에 할당되고 제품군이 실행됩니다. 이것은 반복자가 제공하는 각 항목에 대해 반복됩니다. 반복자가 소진되면 else 절의 스위트(있는 경우)가 실행되고 루프가 종료됩니다.
첫 번째 모음에서 실행되는 break 문은 else 절의 모음을 실행하지 않고 루프를 종료합니다. 첫 번째 스위트에서 실행되는 continue 문은 스위트의 나머지 부분을 건너뛰고 다음 항목으로 계속 진행하거나 다음 항목이 없는 경우 else 절로 계속됩니다.
for 루프는 대상 목록의 변수에 할당합니다. 이렇게 하면 for 루프 제품군에서 만든 변수를 포함하여 해당 변수에 대한 모든 이전 할당을 덮어씁니다.
for i in range(10):
print(i)
i = 5 # this will not affect the for-loop
# because i will be overwritten with the next
# index in the range
대상 목록의 이름은 루프가 종료될 때 삭제되지 않지만 시퀀스가 비어 있으면 루프에 의해 할당되지 않습니다. 힌트: 내장 유형 range()는 정수의 불변 산술 시퀀스를 나타냅니다. 예를 들어 range(3)를 반복하면 0, 1, 2가 차례로 생성됩니다.
버전 3.11에서 변경: 이제 별표 표시된 요소가 표현식 목록에서 허용됩니다.
8.4. The try
statement
try 문은 문 그룹에 대한 예외 처리기 및/또는 정리 코드를 지정합니다.
try_stmt ::= try1_stmt | try2_stmt | try3_stmt
try1_stmt ::= "try" ":" suite
("except" [expression ["as" identifier]] ":" suite)+
["else" ":" suite]
["finally" ":" suite]
try2_stmt ::= "try" ":" suite
("except" "*" expression ["as" identifier] ":" suite)+
["else" ":" suite]
["finally" ":" suite]
try3_stmt ::= "try" ":" suite
"finally" ":" suite
예외에 대한 추가 정보는 예외 섹션에서 찾을 수 있으며, raise 문을 사용하여 예외를 생성하는 방법에 대한 정보는 raise 문 섹션에서 찾을 수 있습니다.
8.4.1. except
clause
except 절은 하나 이상의 예외 핸들러를 지정합니다. try 절에서 예외가 발생하지 않으면 예외 처리기가 실행되지 않습니다. try 제품군에서 예외가 발생하면 예외 처리기 검색이 시작됩니다. 이 검색은 예외와 일치하는 항목을 찾을 때까지 차례로 except 절을 검사합니다. 표현식이 없는 except 절이 있는 경우 마지막이어야 합니다. 모든 예외와 일치합니다. 식이 포함된 except 절의 경우 해당 식이 평가되고 결과 개체가 예외와 “호환”되는 경우 절이 예외와 일치합니다. 개체가 예외 개체의 클래스 또는 비가상 기본 클래스이거나 예외 개체의 클래스 또는 비가상 기본 클래스인 항목을 포함하는 튜플인 경우 개체는 예외와 호환됩니다.
예외와 일치하는 절이 없으면 주변 코드와 호출 스택에서 예외 처리기에 대한 검색이 계속됩니다. 1
except 절의 헤더에 있는 표현식 평가에서 예외가 발생하면 핸들러에 대한 원래 검색이 취소되고 주변 코드와 호출 스택에서 새 예외에 대한 검색이 시작됩니다(전체 try 문에서 예외가 발생했습니다).
일치하는 except 절이 발견되면, 해당 except 절에서 as 키워드 뒤에 지정된 대상에 예외가 할당되고(있는 경우), except 절의 스위트가 실행됩니다. 모든 except 절에는 실행 가능한 블록이 있어야 합니다. 이 블록의 끝에 도달하면 전체 try 문 이후 실행이 정상적으로 계속됩니다. (이는 동일한 예외에 대해 두 개의 중첩 처리기가 존재하고 내부 처리기의 try 절에서 예외가 발생하면 외부 처리기가 예외를 처리하지 않음을 의미합니다.)
대상으로 사용하여 예외가 할당되면 except 절의 끝에서 지워집니다.
이것은 마치 아래 코드가
except E as N:
foo
아래와 같이 번역되는 것과 같습니다.
except E as N:
try:
foo
finally:
del N
즉, except 절 뒤에서 예외를 참조할 수 있으려면 예외를 다른 이름에 지정해야 합니다. 트레이스백이 첨부되어 있기 때문에 예외는 지워집니다. 스택 프레임과 함께 참조 순환을 형성하여 다음 가비지 수집이 발생할 때까지 해당 프레임의 모든 로컬을 활성 상태로 유지합니다.
예외 절의 모음이 실행되기 전에 예외에 대한 세부 정보가 sys 모듈에 저장되고 sys.exc_info()를 통해 액세스할 수 있습니다. sys.exc_info()는 예외 클래스, 예외 인스턴스 및 예외가 발생한 프로그램의 지점을 식별하는 역추적 객체(표준 유형 계층 섹션 참조)로 구성된 3-튜플을 반환합니다. sys.exc_info()를 통해 액세스된 예외에 대한 세부 정보는 예외 처리기를 떠날 때 이전 값으로 복원됩니다.
>>> print(sys.exc_info())
(None, None, None)
>>> try:
... raise TypeError
... except:
... print(sys.exc_info())
... try:
... raise ValueError
... except:
... print(sys.exc_info())
... print(sys.exc_info())
...
(<class 'TypeError'>, TypeError(), <traceback object at 0x10efad080>)
(<class 'ValueError'>, ValueError(), <traceback object at 0x10efad040>)
(<class 'TypeError'>, TypeError(), <traceback object at 0x10efad080>)
>>> print(sys.exc_info())
(None, None, None)
8.4.2. except*
clause
except* 절은 ExceptionGroup을 처리하는 데 사용됩니다. 일치를 위한 예외 유형은 예외의 경우와 같이 해석되지만 예외 그룹의 경우 유형이 그룹의 일부 예외와 일치할 때 부분 일치를 가질 수 있습니다. 즉, 각각 예외 그룹의 일부를 처리하는 여러 except* 절이 실행될 수 있습니다. 각 절은 최대 한 번 실행되며 일치하는 모든 예외의 예외 그룹을 처리합니다. 그룹의 각 예외는 일치하는 첫 번째 절인 최대 하나의 except* 절에 의해 처리됩니다.
>>> try:
... raise ExceptionGroup("eg",
... [ValueError(1), TypeError(2), OSError(3), OSError(4)])
... except* TypeError as e:
... print(f'caught {type(e)} with nested {e.exceptions}')
... except* OSError as e:
... print(f'caught {type(e)} with nested {e.exceptions}')
...
caught <class 'ExceptionGroup'> with nested (TypeError(2),)
caught <class 'ExceptionGroup'> with nested (OSError(3), OSError(4))
+ Exception Group Traceback (most recent call last):
| File "<stdin>", line 2, in <module>
| ExceptionGroup: eg
+-+---------------- 1 ----------------
| ValueError: 1
+------------------------------------
except* 절에 의해 처리되지 않은 나머지 예외는 마지막에 다시 발생하여 except* 절 내에서 발생한 모든 예외와 함께 예외 그룹으로 결합됩니다.
발생한 예외가 예외 그룹이 아니고 해당 유형이 except* 절 중 하나와 일치하는 경우 빈 메시지 문자열이 있는 예외 그룹에 의해 포착되고 래핑됩니다.
>>> try:
... raise BlockingIOError
... except* BlockingIOError as e:
... print(repr(e))
...
ExceptionGroup('', (BlockingIOError()))
except* 절에는 일치하는 유형이 있어야 하며 이 유형은 BaseExceptionGroup의 하위 클래스일 수 없습니다. 같은 시도에서 except와 except*를 함께 사용할 수 없습니다. break, continue 및 return은 except* 절에 나타날 수 없습니다.
8.4.3. else
clause
선택적 else 절은 제어 흐름이 try 제품군을 벗어나고 예외가 발생하지 않았으며 return, continue 또는 break 문이 실행되지 않은 경우 실행됩니다. else 절의 예외는 앞의 except 절에서 처리되지 않습니다.
8.4.4. finally
clause
finally가 있으면 ‘정리’ 처리기를 지정합니다. except 및 else 절을 포함하여 try 절이 실행됩니다. 어느 조항에서든 예외가 발생하여 처리하지 않으면 임시로 예외를 저장합니다. finally 절이 실행됩니다. 저장된 예외가 있으면 finally 절의 끝에서 다시 발생합니다. finally 절이 다른 예외를 발생시키면 저장된 예외가 새 예외의 컨텍스트로 설정됩니다. finally 절이 return, break 또는 continue 문을 실행하면 저장된 예외가 삭제됩니다.
>>> def f():
... try:
... 1/0
... finally:
... return 42
...
>>> f()
42
finally 절을 실행하는 동안 프로그램에서 예외 정보를 사용할 수 없습니다.
return, break 또는 continue 문이 try…finally 문의 try 스위트에서 실행될 때 finally 절도 ‘on the way out’에서 실행됩니다.
함수의 반환 값은 실행된 마지막 반환 문에 의해 결정됩니다. finally 절은 항상 실행되므로 finally 절에서 실행되는 return 문은 항상 마지막으로 실행됩니다.
>>> def foo():
... try:
... return 'try'
... finally:
... return 'finally'
...
>>> foo()
'finally'
버전 3.8에서 변경: 파이썬 3.8 이전에는 구현 문제로 인해 finally 절에서 continue 문이 올바르지 않았습니다.
8.5. The with
statement
with 문은 컨텍스트 관리자가 정의한 메서드로 블록 실행을 래핑하는 데 사용됩니다(With 문 컨텍스트 관리자 섹션 참조). 이를 통해 일반적인 시도…제외…최종 사용 패턴을 캡슐화하여 편리하게 재사용할 수 있습니다.
with_stmt ::= "with" ( "(" with_stmt_contents ","? ")" | with_stmt_contents ) ":" suite
with_stmt_contents ::= with_item ("," with_item)*
with_item ::= expression ["as" target]
하나의 “항목”이 포함된 with 문의 실행은 다음과 같이 진행됩니다.
- 컨텍스트 표현식(with_item에 제공된 표현식)은 컨텍스트 관리자를 얻기 위해 평가됩니다.
- 컨텍스트 관리자의 __enter__()는 나중에 사용하기 위해 로드됩니다.
- 컨텍스트 관리자의 __exit__()는 나중에 사용하기 위해 로드됩니다.
- 컨텍스트 관리자의 __enter__() 메서드가 호출됩니다.
- 대상이 with 문에 포함된 경우 __enter__()의 반환 값이 대상에 할당됩니다.
참고: with 문은 __enter__() 메서드가 오류 없이 반환되면 __exit__()가 항상 호출되도록 보장합니다. 따라서 대상 목록에 할당하는 동안 오류가 발생하면 제품군 내에서 발생하는 오류와 동일하게 처리됩니다. 아래의 7단계를 참조하십시오. - 제품군이 실행됩니다.
- 컨텍스트 관리자의 __exit__() 메서드가 호출됩니다. 예외로 인해 제품군이 종료된 경우, 해당 유형, 값 및 트레이스백이 __exit__()의 인수로 전달됩니다. 그렇지 않으면 세 개의 None 인수가 제공됩니다.
예외로 인해 스위트가 종료되었고 __exit__() 메서드의 반환 값이 거짓이면 예외가 다시 발생합니다. 반환 값이 true이면 예외가 억제되고 with 문 다음의 문으로 실행이 계속됩니다.
예외가 아닌 다른 이유로 스위트가 종료된 경우 __exit__() 의 반환 값은 무시되고 종료된 종류의 정상 위치에서 실행이 진행됩니다.
다음 코드:
with EXPRESSION as TARGET:
SUITE
의미상 다음과 동일합니다.
manager = (EXPRESSION)
enter = type(manager).__enter__
exit = type(manager).__exit__
value = enter(manager)
hit_except = False
try:
TARGET = value
SUITE
except:
hit_except = True
if not exit(manager, *sys.exc_info()):
raise
finally:
if not hit_except:
exit(manager, None, None, None)
둘 이상의 항목이 있는 경우 컨텍스트 관리자는 여러 with 문이 중첩된 것처럼 처리됩니다.
with A() as a, B() as b:
SUITE
의미상 다음과 동일합니다.
with A() as a:
with B() as b:
SUITE
항목이 괄호로 묶인 경우 다중 항목 컨텍스트 관리자를 여러 줄로 작성할 수도 있습니다. 예를 들어:
with (
A() as a,
B() as b,
):
SUITE
버전 3.1에서 변경: 여러 컨텍스트 표현식 지원.
버전 3.10에서 변경: 그룹화 괄호를 사용하여 명령문을 여러 줄로 나누도록 지원합니다.
See also
PEP 343 – The “with” statement
Python with 문에 대한 사양, 배경 및 예제입니다.
8.6. The match
statement
버전 3.10의 새로운 기능.
match 문은 패턴 일치에 사용됩니다. 통사론:
match_stmt ::= 'match' subject_expr ":" NEWLINE INDENT case_block+ DEDENT
subject_expr ::= star_named_expression "," star_named_expressions?
| named_expression
case_block ::= 'case' patterns [guard] ":" block
Note
이 섹션에서는 작은따옴표를 사용하여 소프트 키워드를 나타냅니다.
패턴 매칭은 패턴(다음 사례)과 대상 값(다음 일치)을 입력으로 사용합니다. 패턴(하위 패턴을 포함할 수 있음)은 대상 값과 일치합니다. 결과는 다음과 같습니다.
- 일치 성공 또는 실패(패턴 성공 또는 실패라고도 함).
- 일치하는 값을 이름에 바인딩할 수 있습니다. 이에 대한 전제 조건은 아래에서 자세히 설명합니다.
match 및 case 키워드는 소프트 키워드입니다.
See also
PEP 634 – Structural Pattern Matching: Specification
PEP 636 – Structural Pattern Matching: Tutorial
8.6.1. Overview
다음은 일치 문의 논리적 흐름에 대한 개요입니다.
- 주제 표현식 subject_expr이 평가되고 결과 주제 값이 획득됩니다. 주제 표현식에 쉼표가 포함되어 있으면 표준 규칙을 사용하여 튜플이 생성됩니다.
- case_block의 각 패턴은 주제 값과 일치하도록 시도됩니다. 성공 또는 실패에 대한 구체적인 규칙은 아래에 설명되어 있습니다. 일치 시도는 패턴 내의 독립 실행형 이름의 일부 또는 전체를 바인딩할 수도 있습니다. 정확한 패턴 바인딩 규칙은 패턴 유형에 따라 다르며 아래에 지정되어 있습니다. 성공적인 패턴 일치 중에 만들어진 이름 바인딩은 실행된 블록보다 오래 지속되며 일치 문 뒤에 사용할 수 있습니다.
참고: 실패한 패턴 일치 중에 일부 하위 패턴이 성공할 수 있습니다. 실패한 일치에 대한 바인딩에 의존하지 마십시오. 반대로 일치 실패 후 변경되지 않은 상태로 남아 있는 변수에 의존하지 마십시오. 정확한 동작은 구현에 따라 다르며 다를 수 있습니다. 이는 다양한 구현에서 최적화를 추가할 수 있도록 의도적으로 내린 결정입니다.
- 패턴이 성공하면 해당 가드(있는 경우)가 평가됩니다. 이 경우 모든 이름 바인딩이 발생한 것으로 보장됩니다.
- 가드가 true로 평가되거나 누락된 경우 case_block 내부의 블록이 실행됩니다.
- 그렇지 않으면 위에서 설명한 대로 다음 case_block이 시도됩니다.
- 추가 케이스 블록이 없으면 일치 문이 완료됩니다.
참고: 일반적으로 사용자는 평가 중인 패턴에 의존해서는 안 됩니다. 구현에 따라 인터프리터는 값을 캐시하거나 반복 평가를 건너뛰는 다른 최적화를 사용할 수 있습니다.
샘플 일치 문:
>>> flag = False
>>> match (100, 200):
... case (100, 300): # Mismatch: 200 != 300
... print('Case 1')
... case (100, 200) if flag: # Successful match, but guard fails
... print('Case 2')
... case (100, y): # Matches and binds y to 200
... print(f'Case 3, y: {y}')
... case _: # Pattern not attempted
... print('Case 4, I match anything!')
...
Case 3, y: 200
이 경우 if flag는 가드입니다. 다음 섹션에서 이에 대해 자세히 알아보세요.
8.6.2. Guards
guard ::= "if" named_expression
케이스 블록 내부의 코드가 실행되려면 가드(케이스의 일부)가 성공해야 합니다. 다음과 같은 형식을 취합니다: 표현식 뒤에 오는 경우.
가드가 있는 케이스 블록의 논리적 흐름은 다음과 같습니다.
- 케이스 블록의 패턴이 성공했는지 확인하십시오. 패턴이 실패하면 가드가 평가되지 않고 다음 케이스 블록이 확인됩니다.
- 패턴이 성공하면 가드를 평가하십시오.
- 가드 조건이 참으로 평가되면 케이스 블록이 선택됩니다.
- 가드 조건이 거짓으로 평가되면 케이스 블록이 선택되지 않습니다.
- 가드가 평가 중에 예외를 발생시키면 예외가 발생합니다.
가드는 표현식이기 때문에 부작용이 있을 수 있습니다. 가드 평가는 패턴이 모두 성공하지 않는 경우 블록을 건너뛰고 한 번에 하나씩 첫 번째 사례 블록에서 마지막 사례 블록까지 진행해야 합니다. (즉, 가드 평가는 순서대로 이루어져야 합니다.) 가드 평가는 케이스 블록이 선택되면 중지해야 합니다.
8.6.3. Irrefutable Case Blocks
반박 불가능한 케이스 블록은 모두 일치하는 케이스 블록입니다. 일치 문에는 반박할 수 없는 사례 블록이 최대 하나 있을 수 있으며 마지막이어야 합니다.
가드가 없고 패턴이 반박 불가능한 경우 케이스 블록은 반박 불가능한 것으로 간주됩니다. 구문만으로 항상 성공할 것이라는 것을 증명할 수 있는 패턴은 반박할 수 없는 것으로 간주됩니다. 반박할 수 없는 패턴은 다음과 같습니다.
- 왼쪽이 반박할 수 없는 AS 패턴
- 반박할 수 없는 패턴이 하나 이상 포함된 OR 패턴
- 캡처 패턴
- 와일드카드 패턴
- 반박할 수 없는 괄호 패턴
8.6.4. Patterns
Note
이 섹션에서는 표준 EBNF 이외의 문법 표기법을 사용합니다.
표기법 SEP.RULE+는 RULE(SEP RULE)*의 줄임말입니다.
표기법 !RULE은 부정적인 예측 어설션의 줄임말입니다.
패턴의 최상위 구문은 다음과 같습니다.
patterns ::= open_sequence_pattern | pattern
pattern ::= as_pattern | or_pattern
closed_pattern ::= | literal_pattern
| capture_pattern
| wildcard_pattern
| value_pattern
| group_pattern
| sequence_pattern
| mapping_pattern
| class_pattern
아래 설명에는 설명 목적으로 패턴이 수행하는 작업에 대한 “간단한 용어로” 설명이 포함됩니다(대부분의 설명에 영감을 준 문서에 대한 Raymond Hettinger의 공로). 이러한 설명은 순전히 설명을 위한 것이며 기본 구현을 반영하지 않을 수 있습니다. 또한 모든 유효한 양식을 다루지는 않습니다.
8.6.4.1. OR Patterns
OR 패턴은 세로 막대 |로 구분된 둘 이상의 패턴입니다. 통사론:
or_pattern ::= "|".closed_pattern+
최종 하위 패턴만 반박할 수 없으며 각 하위 패턴은 모호성을 피하기 위해 동일한 이름 집합을 바인딩해야 합니다.
OR 패턴은 하나가 성공할 때까지 각 하위 패턴을 대상 값과 차례로 일치시킵니다. 그러면 OR 패턴이 성공한 것으로 간주됩니다. 그렇지 않고 성공하는 하위 패턴이 없으면 OR 패턴이 실패합니다.
간단히 말해서 P1 | P2 | … P1과 일치시키려고 시도하고, 실패하면 P2와 일치시키려고 시도합니다. 성공하면 즉시 성공하고 그렇지 않으면 실패합니다.
8.6.4.2. AS Patterns
AS 패턴은 주제에 대해 as 키워드 왼쪽의 OR 패턴과 일치합니다. 통사론:
as_pattern ::= or_pattern "as" capture_pattern
OR 패턴이 실패하면 AS 패턴도 실패합니다. 그렇지 않으면 AS 패턴은 주제를 as 키워드 오른쪽에 있는 이름에 바인딩하고 성공합니다. capture_pattern은 _일 수 없습니다.
간단히 말해서 P as NAME은 P와 일치하고 성공하면 NAME = 로 설정됩니다.
8.6.4.3. Literal Patterns
리터럴 패턴은 파이썬에서 대부분의 리터럴에 해당합니다. 통사론:
literal_pattern ::= signed_number
| signed_number "+" NUMBER
| signed_number "-" NUMBER
| strings
| "None"
| "True"
| "False"
| signed_number: NUMBER | "-" NUMBER
규칙 문자열과 토큰 NUMBER는 표준 Python 문법에 정의되어 있습니다. 삼중 인용 문자열이 지원됩니다. 원시 문자열과 바이트 문자열이 지원됩니다. 형식이 지정된 문자열 리터럴은 지원되지 않습니다.
signed_number ‘+’ NUMBER 및 signed_number ‘-‘ NUMBER 형식은 복소수를 표현하기 위한 것입니다. 왼쪽에는 실수가, 오른쪽에는 허수가 필요합니다. 예를 들어 3 + 4j.
간단히 말해서 LITERAL은 == LITERAL인 경우에만 성공합니다. 싱글톤 None, True 및 False의 경우 is 연산자가 사용됩니다.
8.6.4.4. Capture Patterns
캡처 패턴은 주체 값을 이름에 바인딩합니다. 통사론:
capture_pattern ::= !'_' NAME
하나의 밑줄 _은 캡처 패턴이 아닙니다(이것은 !’_’가 표현하는 것입니다). 대신 wildcard_pattern으로 처리됩니다.
지정된 패턴에서 지정된 이름은 한 번만 바인딩될 수 있습니다. 예를 들어 case x, x: …는 case [x] | 동안 유효하지 않습니다. x: … 허용됩니다.
캡처 패턴은 항상 성공합니다. 바인딩은 PEP 572의 할당 표현식 연산자에 의해 설정된 범위 지정 규칙을 따릅니다. 해당 이름은 적용 가능한 전역 또는 비지역 문이 없는 한 가장 가까운 포함 함수 범위에서 지역 변수가 됩니다.
간단히 말해서 NAME은 항상 성공하며 NAME = 로 설정됩니다.
8.6.4.5. Wildcard Patterns
와일드카드 패턴은 항상 성공하고(무엇이든 일치) 이름을 바인딩하지 않습니다. 통사론:
wildcard_pattern ::= '_'
_는 모든 패턴 내에서 소프트 키워드이지만 패턴 내에서만 가능합니다. 일치 주제 표현식, 가드 및 케이스 블록 내에서도 평소와 같이 식별자입니다.
간단히 말해서 _는 항상 성공할 것입니다.
8.6.4.6. Value Patterns
값 패턴은 Python에서 명명된 값을 나타냅니다. 통사론:
value_pattern ::= attr
attr ::= name_or_attr "." NAME
name_or_attr ::= attr | NAME
패턴의 점으로 구분된 이름은 표준 Python 이름 확인 규칙을 사용하여 조회됩니다. 찾은 값이 대상 값과 같다고 비교하면 패턴이 성공한 것입니다(== 같음 연산자 사용).
간단히 말해서 NAME1.NAME2는 == NAME1.NAME2인 경우에만 성공합니다.
참고: 동일한 일치 문에서 동일한 값이 여러 번 발생하는 경우 인터프리터는 찾은 첫 번째 값을 캐시하고 동일한 조회를 반복하는 대신 재사용할 수 있습니다. 이 캐시는 지정된 일치 문의 지정된 실행과 엄격하게 연결되어 있습니다.
8.6.4.7. Group Patterns
그룹 패턴을 사용하면 패턴 주위에 괄호를 추가하여 의도한 그룹화를 강조할 수 있습니다. 그렇지 않으면 추가 구문이 없습니다. 통사론:
group_pattern ::= "(" pattern ")"
간단히 말해서 (P)는 P와 같은 효과를 가집니다.
8.6.4.8. Sequence Patterns
시퀀스 패턴에는 시퀀스 요소와 일치시킬 여러 하위 패턴이 포함되어 있습니다. 구문은 목록 또는 튜플의 압축을 푸는 것과 비슷합니다.
sequence_pattern ::= "[" [maybe_sequence_pattern] "]"
| "(" [open_sequence_pattern] ")"
open_sequence_pattern ::= maybe_star_pattern "," [maybe_sequence_pattern]
maybe_sequence_pattern ::= ",".maybe_star_pattern+ ","?
maybe_star_pattern ::= star_pattern | pattern
star_pattern ::= "*" (capture_pattern | wildcard_pattern)
시퀀스 패턴(즉, (…) 대 […] )에 괄호나 대괄호를 사용하는 경우에는 차이가 없습니다.
참고: 후행 쉼표 없이 괄호로 묶인 단일 패턴(예: (3 | 4))은 그룹 패턴입니다. 대괄호로 묶인 단일 패턴(예: [3 | 4])은 여전히 시퀀스 패턴입니다.
최대 하나의 스타 하위 패턴이 시퀀스 패턴에 있을 수 있습니다. 별 모양의 하위 패턴은 어느 위치에서나 나타날 수 있습니다. 스타 하위 패턴이 없으면 시퀀스 패턴은 고정 길이 시퀀스 패턴입니다. 그렇지 않으면 가변 길이 시퀀스 패턴입니다.
다음은 주제 값에 대해 시퀀스 패턴을 일치시키는 논리적 흐름입니다.
- 대상 값이 시퀀스 2가 아니면 시퀀스 패턴이 실패합니다.
- 대상 값이 str, bytes 또는 bytearray의 인스턴스인 경우 시퀀스 패턴이 실패합니다.
- 후속 단계는 시퀀스 패턴이 고정 길이인지 가변 길이인지에 따라 다릅니다.
- 시퀀스 패턴이 고정 길이인 경우:
- 대상 시퀀스의 길이가 서브 패턴의 수와 같지 않으면 시퀀스 패턴이 실패합니다.
- 시퀀스 패턴의 하위 패턴은 왼쪽에서 오른쪽으로 대상 시퀀스의 해당 항목과 일치합니다. 하위 패턴이 실패하는 즉시 매칭이 중지됩니다. 모든 하위 패턴이 해당 항목 일치에 성공하면 시퀀스 패턴이 성공합니다.
- 그렇지 않고 시퀀스 패턴이 가변 길이인 경우:
- 대상 시퀀스의 길이가 별이 아닌 하위 패턴의 수보다 작으면 시퀀스 패턴이 실패합니다.
- 고정 길이 시퀀스의 경우 선행 비스타 하위 패턴은 해당 항목과 일치합니다.
- 이전 단계가 성공하면 별 하위 패턴은 별 하위 패턴 다음에 오는 비별 하위 패턴에 해당하는 나머지 항목을 제외하고 나머지 주제 항목으로 구성된 목록과 일치합니다.
- 나머지 비별 하위 패턴은 고정 길이 시퀀스와 마찬가지로 해당 주제 항목과 일치합니다.
- 시퀀스 패턴이 고정 길이인 경우:
참고: 대상 시퀀스의 길이는 len()을 통해(즉, __len__() 프로토콜을 통해) 얻습니다. 이 길이는 값 패턴과 유사한 방식으로 인터프리터에 의해 캐시될 수 있습니다.
간단히 말해서 [P1, P2, P3, … , P]은 다음과 같은 경우에만 일치합니다.
-
<subject>
이 시퀀스인지 확인하십시오. len(subject) == <N>
- P1은 <subject>[0]과 일치합니다(이 일치는 이름을 바인딩할 수도 있음).
- P2는 <subject>[1]과 일치합니다(이 일치는 이름을 바인딩할 수도 있음).
- … 그리고 해당 패턴/요소에 대해 등등.
8.6.4.9. Mapping Patterns
매핑 패턴에는 하나 이상의 키-값 패턴이 포함됩니다. 구문은 사전 구성과 유사합니다. 통사론:
mapping_pattern ::= "{" [items_pattern] "}"
items_pattern ::= ",".key_value_pattern+ ","?
key_value_pattern ::= (literal_pattern | value_pattern) ":" pattern
| double_star_pattern
double_star_pattern ::= "**" capture_pattern
최대 하나의 이중 별 패턴이 매핑 패턴에 있을 수 있습니다. 이중 별 패턴은 매핑 패턴의 마지막 하위 패턴이어야 합니다.
매핑 패턴의 중복 키는 허용되지 않습니다. 중복 리터럴 키는 SyntaxError를 발생시킵니다. 그렇지 않으면 동일한 값을 갖는 두 개의 키가 런타임에 ValueError를 발생시킵니다.
다음은 주체 값에 대해 매핑 패턴을 일치시키는 논리적 흐름입니다.
- 대상 값이 매핑 3이 아닌 경우 매핑 패턴이 실패합니다.
- 매핑 패턴에 주어진 모든 키가 주체 매핑에 존재하고 각 키의 패턴이 주체 매핑의 해당 항목과 일치하면 매핑 패턴이 성공합니다.
- 매핑 패턴에서 중복 키가 감지되면 패턴이 잘못된 것으로 간주됩니다. 중복 리터럴 값에 대해 SyntaxError 가 발생합니다; 또는 동일한 값의 명명된 키에 대한 ValueError입니다.
참고: 키-값 쌍은 매핑 주체의 get() 메서드의 두 인수 형식을 사용하여 일치합니다. 일치하는 키-값 쌍은 매핑에 이미 존재해야 하며 __missing__() 또는 __getitem__()을 통해 즉석에서 생성되지 않아야 합니다.
간단히 말해서 {KEY1: P1, KEY2: P2, … }는 다음이 모두 발생하는 경우에만 일치합니다.
-
<subject>
이 매핑인지 확인 KEY1 in <subject>
- P1은 <subject>[KEY1]과 일치합니다.
- … 그리고 해당 키/패턴 쌍에 대해 등등.
8.6.4.10. Class Patterns
클래스 패턴은 클래스와 해당 위치 및 키워드 인수(있는 경우)를 나타냅니다. 통사론:
class_pattern ::= name_or_attr "(" [pattern_arguments ","?] ")"
pattern_arguments ::= positional_patterns ["," keyword_patterns]
| keyword_patterns
positional_patterns ::= ",".pattern+
keyword_patterns ::= ",".keyword_pattern+
keyword_pattern ::= NAME "=" pattern
동일한 키워드가 클래스 패턴에서 반복되어서는 안 됩니다.
다음은 주제 값에 대해 클래스 패턴을 일치시키는 논리적 흐름입니다.
- name_or_attr이 내장 type의 인스턴스가 아니면 TypeError를 발생시킵니다.
- 대상 값이 name_or_attr(isinstance()를 통해 테스트됨)의 인스턴스가 아니면 클래스 패턴이 실패합니다.
- 패턴 인수가 없으면 패턴이 성공합니다. 그렇지 않으면 후속 단계는 키워드 또는 위치 인수 패턴이 있는지 여부에 따라 달라집니다.
여러 기본 제공 유형(아래에 지정됨)의 경우 전체 주제와 일치하는 단일 위치 하위 패턴이 허용됩니다. 이러한 유형의 키워드 패턴은 다른 유형과 마찬가지로 작동합니다.- 키워드 패턴만 있는 경우 다음과 같이 하나씩 처리됩니다.
- 키워드는 주제에 대한 속성으로 조회됩니다.
- 이로 인해 AttributeError 이외의 예외가 발생하면 예외가 발생합니다.
- 이로 인해 AttributeError가 발생하면 클래스 패턴이 실패한 것입니다.
- 그렇지 않으면 키워드 패턴과 관련된 하위 패턴이 주제의 속성 값과 일치합니다. 이것이 실패하면 클래스 패턴이 실패합니다. 이것이 성공하면 일치가 다음 키워드로 진행됩니다.
- 모든 키워드 패턴이 성공하면 클래스 패턴이 성공합니다.
- 키워드는 주제에 대한 속성으로 조회됩니다.
- 위치 패턴이 있으면 일치하기 전에 name_or_attr 클래스의 __match_args__ 속성을 사용하여 키워드 패턴으로 변환됩니다.
- getattr(cls, “__match_args__”, ()) 와 동등한 것이 호출됩니다.
- 이로 인해 예외가 발생하면 예외가 발생합니다.
- 반환된 값이 튜플이 아니면 변환이 실패하고 TypeError가 발생합니다.
- len(cls.__match_args__)보다 더 많은 위치 패턴이 있으면 TypeError가 발생합니다.
- 그렇지 않으면 위치 패턴 i가 __match_args__[i]를 키워드로 사용하여 키워드 패턴으로 변환됩니다. __match_args__[i]는 문자열이어야 합니다. 그렇지 않으면 TypeError가 발생합니다.
- 중복 키워드가 있으면 TypeError가 발생합니다.
- 클래스 패턴 일치에서 위치 인수 사용자 정의도 참조하십시오.
- 모든 위치 패턴이 키워드 패턴으로 변환되면, 키워드 패턴만 있는 것처럼 일치가 진행됩니다.
- getattr(cls, “__match_args__”, ()) 와 동등한 것이 호출됩니다.
- 다음 내장 유형의 경우 위치 하위 패턴 처리가 다릅니다.
- bool
- bytearray
- bytes
- dict
- float
- frozenset
- int
- list
- set
- str
- tuple
- 이러한 클래스는 단일 위치 인수를 허용하고 거기에 있는 패턴은 특성이 아닌 전체 개체와 일치합니다. 예를 들어 int(0|1)은 값 0과 일치하지만 값 0.0과는 일치하지 않습니다.
- 키워드 패턴만 있는 경우 다음과 같이 하나씩 처리됩니다.
간단히 말해서 CLS(P1, attr=P2)는 다음과 같은 경우에만 일치합니다.
- isinstance(<제목>, CLS)
- CLS.__match_args__를 사용하여 P1을 키워드 패턴으로 변환
- 각 키워드 인수 attr=P2에 대해:
- hasattr(<제목>, “attr”)
- P2는 <제목>.attr과 일치합니다.
- … 해당 키워드 인수/패턴 쌍에 대해 등등.
See also
PEP 634 – Structural Pattern Matching: Specification
PEP 636 – Structural Pattern Matching: Tutorial
8.7. Function definitions
함수 정의는 사용자 정의 함수 개체를 정의합니다(표준 유형 계층 섹션 참조).
funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")"
["->" expression] ":" suite
decorators ::= decorator+
decorator ::= "@" assignment_expression NEWLINE
parameter_list ::= defparameter ("," defparameter)* "," "/" ["," [parameter_list_no_posonly]]
| parameter_list_no_posonly
parameter_list_no_posonly ::= defparameter ("," defparameter)* ["," [parameter_list_starargs]]
| parameter_list_starargs
parameter_list_starargs ::= "*" [parameter] ("," defparameter)* ["," ["**" parameter [","]]]
| "**" parameter [","]
parameter ::= identifier [":" expression]
defparameter ::= parameter ["=" expression]
funcname ::= identifier
함수 정의는 실행 가능한 명령문입니다. 해당 실행은 현재 로컬 네임스페이스의 함수 이름을 함수 개체(함수에 대한 실행 코드 주위의 래퍼)에 바인딩합니다. 이 함수 개체에는 함수가 호출될 때 사용될 전역 네임스페이스로 현재 전역 네임스페이스에 대한 참조가 포함되어 있습니다.
함수 정의는 함수 본문을 실행하지 않습니다. 이것은 함수가 호출될 때만 실행됩니다.
함수 정의는 하나 이상의 데코레이터 표현식으로 래핑될 수 있습니다. 데코레이터 식은 함수 정의가 포함된 범위에서 함수가 정의될 때 평가됩니다. 결과는 함수 개체를 유일한 인수로 사용하여 호출되는 콜러블이어야 합니다. 반환된 값은 함수 개체 대신 함수 이름에 바인딩됩니다. 여러 데코레이터가 중첩 방식으로 적용됩니다. 예를 들어, 다음 코드
@f1(arg)
@f2
def func(): pass
는 대략 다음과 같습니다.
def func(): pass
func = f1(arg)(f2(func))
원래 함수가 일시적으로 func라는 이름에 바인딩되지 않는다는 점만 다릅니다.
버전 3.9에서 변경: 함수는 유효한 assignment_expression으로 장식될 수 있습니다. 이전에는 문법이 훨씬 더 제한적이었습니다. 자세한 내용은 PEP 614를 참조하십시오.
하나 이상의 매개변수가 매개변수 = 표현식 형식이면 함수에 “기본 매개변수 값”이 있다고 합니다. 기본값이 있는 매개변수의 경우 호출에서 해당 인수를 생략할 수 있으며 이 경우 매개변수의 기본값이 대체됩니다. 매개변수에 기본값이 있는 경우 “*”까지 이어지는 모든 매개변수에도 기본값이 있어야 합니다. 이는 문법으로 표현되지 않는 구문 제한입니다.
기본 매개변수 값은 함수 정의가 실행될 때 왼쪽에서 오른쪽으로 평가됩니다. 이는 함수가 정의될 때 표현식이 한 번 평가되고 동일한 “사전 계산된” 값이 각 호출에 사용됨을 의미합니다. 이는 기본 매개변수 값이 목록이나 사전과 같은 가변 객체일 때 이해하는 데 특히 중요합니다. 함수가 객체를 수정하면(예: 목록에 항목 추가) 기본 매개변수 값이 사실상 수정됩니다. 이것은 일반적으로 의도한 바가 아닙니다. 이 문제를 해결하는 방법은 None을 기본값으로 사용하고 함수 본문에서 이를 명시적으로 테스트하는 것입니다. 예를 들면 다음과 같습니다.
def whats_on_the_telly(penguin=None):
if penguin is None:
penguin = []
penguin.append("property of the zoo")
return penguin
함수 호출 의미 체계는 호출 섹션에서 자세히 설명합니다. 함수 호출은 항상 위치 인수, 키워드 인수 또는 기본값에서 매개변수 목록에 언급된 모든 매개변수에 값을 할당합니다. “*identifier” 형식이 있으면 초과 위치 매개변수를 수신하는 튜플로 초기화되며 기본값은 빈 튜플입니다. “**식별자” 형식이 있는 경우 초과 키워드 인수를 수신하는 새로운 정렬 매핑으로 초기화되며, 기본값은 동일한 유형의 새로운 빈 매핑입니다. “*” 또는 “*identifier” 뒤의 매개변수는 키워드 전용 매개변수이며 키워드 인수로만 전달될 수 있습니다. “/” 앞의 매개변수는 위치 전용 매개변수이며 위치 인수로만 전달될 수 있습니다.
버전 3.8에서 변경: / 함수 매개변수 구문은 위치 전용 매개변수를 나타내는 데 사용될 수 있습니다. 자세한 내용은 PEP 570을 참조하십시오.
매개변수에는 매개변수 이름 다음에 “:식” 형식의 주석이 있을 수 있습니다. 모든 매개변수에는 *식별자 또는 **식별자 형식의 주석을 포함하여 주석이 있을 수 있습니다. 함수는 매개변수 목록 뒤에 “-> 표현식” 형식의 “return” 주석이 있을 수 있습니다. 이러한 주석은 유효한 Python 표현식일 수 있습니다. 주석의 존재는 함수의 의미 체계를 변경하지 않습니다. 주석 값은 함수 객체의 __annotations__ 속성에 있는 매개변수 이름으로 키가 지정된 사전의 값으로 사용할 수 있습니다. __future__에서 주석 가져오기를 사용하는 경우 주석은 연기된 평가를 가능하게 하는 런타임 시 문자열로 보존됩니다. 그렇지 않으면 함수 정의가 실행될 때 평가됩니다. 이 경우 주석은 소스 코드에 나타나는 것과 다른 순서로 평가될 수 있습니다.
식에서 즉시 사용하기 위해 익명 함수(이름에 바인딩되지 않은 함수)를 만드는 것도 가능합니다. 이는 람다 섹션에 설명된 람다 식을 사용합니다. 람다 식은 단순한 함수 정의의 약칭일 뿐입니다. “def” 문에 정의된 함수는 람다 식으로 정의된 함수처럼 전달되거나 다른 이름에 할당될 수 있습니다. “def” 형식은 여러 문과 주석을 실행할 수 있기 때문에 실제로 더 강력합니다.
프로그래머 메모: 함수는 일급 개체입니다. 함수 정의 내에서 실행되는 “def” 문은 반환되거나 전달될 수 있는 로컬 함수를 정의합니다. 중첩 함수에 사용되는 자유 변수는 def를 포함하는 함수의 로컬 변수에 액세스할 수 있습니다. 자세한 내용은 이름 지정 및 바인딩 섹션을 참조하십시오.
See also
PEP 3107 – Function Annotations
함수 주석의 원래 사양입니다.
PEP 484 – Type Hints
주석의 표준 의미 정의: 유형 힌트.
PEP 526 – Syntax for Variable Annotations
클래스 변수 및 인스턴스 변수를 포함한 힌트 변수 선언을 입력하는 기능
PEP 563 – Postponed Evaluation of Annotations
즉시 평가하는 대신 런타임에 주석을 문자열 형식으로 유지하여 주석 내 전방 참조를 지원합니다.
8.8. Class definitions
클래스 정의는 클래스 객체를 정의합니다(표준 유형 계층 섹션 참조).
classdef ::= [decorators] "class" classname [inheritance] ":" suite
inheritance ::= "(" [argument_list] ")"
classname ::= identifier
클래스 정의는 실행 가능한 문입니다. 상속 목록은 일반적으로 기본 클래스 목록을 제공하므로(고급 사용에 대해서는 메타클래스 참조) 목록의 각 항목은 서브클래싱을 허용하는 클래스 개체로 평가되어야 합니다. 상속 목록이 없는 클래스는 기본적으로 기본 클래스 개체에서 상속됩니다. 따라서, 아래 코드는
class Foo:
pass
아래코드와 동일하게 취급됩니다.
class Foo(object):
pass
그런 다음 클래스 제품군은 새로 생성된 로컬 네임스페이스와 원래 전역 네임스페이스를 사용하여 새 실행 프레임(네이밍 및 바인딩 참조)에서 실행됩니다. (일반적으로 스위트에는 대부분 함수 정의가 포함되어 있습니다.) 클래스의 스위트가 실행을 마치면 실행 프레임은 폐기되지만 로컬 네임스페이스는 저장됩니다. 5 그러면 기본 클래스의 상속 목록과 속성 사전의 저장된 로컬 네임스페이스를 사용하여 클래스 객체가 생성됩니다. 클래스 이름은 원래 로컬 네임스페이스의 이 클래스 개체에 바인딩됩니다.
속성이 클래스 본문에 정의된 순서는 새 클래스의 __dict__에서 유지됩니다. 이것은 클래스가 생성된 직후에만 그리고 정의 구문을 사용하여 정의된 클래스에 대해서만 신뢰할 수 있습니다.
클래스 생성은 메타클래스를 사용하여 크게 사용자 지정할 수 있습니다.
클래스도 꾸밀 수 있습니다: 함수를 꾸밀 때처럼,
@f1(arg)
@f2
class Foo: pass
는 대략 다음과 같습니다.
class Foo: pass
Foo = f1(arg)(f2(Foo))
데코레이터 표현식의 평가 규칙은 함수 데코레이터와 동일합니다. 그런 다음 결과는 클래스 이름에 바인딩됩니다.
버전 3.9에서 변경: 클래스는 유효한 assignment_expression으로 장식될 수 있습니다. 이전에는 문법이 훨씬 더 제한적이었습니다. 자세한 내용은 PEP 614를 참조하십시오.
프로그래머 참고 사항: 클래스 정의에 정의된 변수는 클래스 속성입니다. 인스턴스에서 공유됩니다. 인스턴스 속성은 self.name = value인 메소드에서 설정할 수 있습니다. 클래스 속성과 인스턴스 속성 모두 “self.name” 표기법을 통해 액세스할 수 있으며 인스턴스 속성은 이러한 방식으로 액세스할 때 동일한 이름을 가진 클래스 속성을 숨깁니다. 클래스 속성은 인스턴스 속성의 기본값으로 사용할 수 있지만 변경 가능한 값을 사용하면 예기치 않은 결과가 발생할 수 있습니다. 디스크립터를 사용하여 구현 세부 정보가 다른 인스턴스 변수를 만들 수 있습니다.
See also
PEP 3115 – Metaclasses in Python 3000
메타클래스의 선언을 현재 구문으로 변경한 제안 및 메타클래스가 있는 클래스가 구성되는 방법에 대한 의미 체계.
PEP 3129 – Class Decorators
클래스 데코레이터를 추가한 제안. 함수 및 메서드 데코레이터는 PEP 318에 도입되었습니다.
8.9. Coroutines
버전 3.5의 새로운 기능.
8.9.1. Coroutine function definition
async_funcdef ::= [decorators] "async" "def" funcname "(" [parameter_list] ")"
["->" expression] ":" suite
Python 코루틴의 실행은 여러 지점에서 일시 중지 및 재개될 수 있습니다(코루틴 참조). await 식, async for 및 async with는 코루틴 함수의 본문에서만 사용할 수 있습니다.
async def 구문으로 정의된 함수는 await 또는 async 키워드를 포함하지 않더라도 항상 코루틴 함수입니다.
코루틴 함수 본문 내에서 표현식에서 yield를 사용하는 것은 SyntaxError입니다.
코루틴 함수의 예:
async def func(param1, param2):
do_stuff()
await some_coroutine()
버전 3.7에서 변경: await 및 async는 이제 키워드입니다. 이전에는 코루틴 함수의 본문 내에서만 그렇게 취급되었습니다.
8.9.2. The async for
statement
async_for_stmt ::= "async" for_stmt
비동기 이터러블은 __anext__ 메서드에서 비동기 코드를 호출할 수 있는 비동기 이터레이터를 직접 반환하는 __aiter__ 메서드를 제공합니다.
async for 문은 비동기 iterable에 대한 편리한 반복을 허용합니다.
다음 코드:
async for TARGET in ITER:
SUITE
else:
SUITE2
의미상 다음과 동일합니다.
iter = (ITER)
iter = type(iter).__aiter__(iter)
running = True
while running:
try:
TARGET = await type(iter).__anext__(iter)
except StopAsyncIteration:
running = False
else:
SUITE
else:
SUITE2
자세한 내용은 __aiter__() 및 __anext__() 도 참조하십시오.
코루틴 함수 본문 외부에서 async for 문을 사용하는 것은 SyntaxError입니다.
8.9.3. The async with
statement
async_with_stmt ::= "async" with_stmt
비동기 컨텍스트 관리자는 enter 및 exit 메서드에서 실행을 일시 중단할 수 있는 컨텍스트 관리자입니다.
다음 코드:
async with EXPRESSION as TARGET:
SUITE
의미상 다음과 동일합니다.
manager = (EXPRESSION)
aenter = type(manager).__aenter__
aexit = type(manager).__aexit__
value = await aenter(manager)
hit_except = False
try:
TARGET = value
SUITE
except:
hit_except = True
if not await aexit(manager, *sys.exc_info()):
raise
finally:
if not hit_except:
await aexit(manager, None, None, None)
자세한 내용은 __aenter__() 및 __aexit__() 도 참조하십시오.
코루틴 함수 본문 외부에서 async with 문을 사용하는 것은 SyntaxError입니다.
See also
PEP 492 – async 및 await 구문이 있는 코루틴
코루틴을 Python에서 적절한 독립형 개념으로 만들고 지원 구문을 추가한 제안.
Source: https://docs.python.org/3/reference/compound_stmts.html