8. 복합문(Compound statements)
******************************

복합문은 다른 문장들(의 그룹들)을 포함합니다; 어떤 방법으로 그 다른 문
장들의 실행에 영향을 주거나 제어합니다. 간단하게 표현할 때, 전체 복합
문을 한 줄로 쓸 수 있기는 하지만, 일반적으로 복합문은 여러 줄에 걸칩니
다.

"if", "while", "for" 문장은 전통적인 제어 흐름 구조를 구현합니다. 문장
들의 그룹에 대해 "try" 는 예외 처리기나 정리(cleanup) 코드 또는 그 둘
모두를 지정하는 반면, "with" 문은 코드 블록 주변으로 초기화와 파이널리
제이션 코드를 실행할 수 있도록 합니다. 함수와 클래스 정의 또한 문법적
으로 복합문입니다.

복합문은 하나나 그 이상의 '절'로 구성됩니다. 절은 헤더와 '스위트
(suite)'로 구성됩니다. 특정 복합문의 절 헤더들은 모두 같은 들여쓰기 수
준을 갖습니다. 각 절 헤더는 특별하게 식별되는 키워드로 시작하고 콜론으
로 끝납니다. 스위트는 절에 의해 제어되는 문장들의 그룹입니다. 스위트는
헤더의 콜론 뒤에서 같은 줄에 세미콜론으로 분리된 하나나 그 이상의 단순
문일 수 있습니다. 또는 그다음 줄에 들여쓰기 된 하나나 그 이상의 문장들
일 수도 있습니다. 오직 후자의 형태만 중첩된 복합문을 포함할 수 있습니
다; 다음과 같은 것은 올바르지 않은데, 대체로 뒤따르는 "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
                     | 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" 가 그 뒤를 따를 수 있음에
주목해야 합니다. 또한, 생략 가능한 연결 절들이 항상 문장을 시작시킬 수
없는 키워드로 시작하기 때문에, 모호함이 없다는 것도 주목하세요 (파이썬
에서는 중첩된 "if" 문이 들여쓰기 되는 것을 요구함으로써 '매달린
(dangling) "else"' 문제를 해결합니다).

명확함을 위해 다음에 오는 절들에서 나오는 문법 규칙들은 각 절을 별도의
줄에 놓도록 포매팅합니다.


8.1. "if" 문
============

"if" 문은 조건부 실행에 사용됩니다:

   if_stmt ::= "if" expression ":" suite
               ("elif" expression ":" suite)*
               ["else" ":" suite]

참이 되는 것을 발견할 때까지 표현식들의 값을 하나씩 차례대로 구해서 정
확히 하나의 스위트를 선택합니다 (참과 거짓의 정의는 논리 연산(Boolean
operations) 섹션을 보세요); 그런 다음 그 스위트를 실행합니다 (그리고는
"if" 문의 다른 어떤 부분도 실행되거나 값이 구해지지 않습니다). 모든 표
현식들이 거짓이면 "else" 절의 스위트가 (있다면) 실행됩니다.


8.2. "while" 문
===============

"while" 문은 표현식이 참인 동안 실행을 반복하는 데 사용됩니다:

   while_stmt ::= "while" expression ":" suite
                  ["else" ":" suite]

이것은 표현식을 반복적으로 검사하고, 참이면, 첫 번째 스위트를 실행합니
다; 표현식이 거짓이면 (처음부터 거짓일 수도 있습니다) "else" 절의 스위
트가 (있다면) 실행되고 루프를 종료합니다.

첫 번째 스위트에서 실행되는 "break" 문은 "else" 절을 실행하지 않고 루
프를 종료합니다. 첫 번째 스위트에서 실행되는 "continue" 문은 스위트의
나머지 부분을 건너뛰고 표현식의 검사로 돌아갑니다.


8.3. "for" 문
=============

"for" 문은 (문자열, 튜플, 리스트 같은) 시퀀스 나 다른 이터러블 객체의
요소들을 이터레이트하는데 사용됩니다:

   for_stmt ::= "for" target_list "in" expression_list ":" suite
                ["else" ":" suite]

표현식 목록은 한 번만 값이 구해집니다; 이터러블 객체가 나와야 합니다.
"expression_list" 의 결과로 이터레이터가 만들어집니다. 그런 다음 이터
레이터가 제공하는 항목마다, 이터레이터가 돌려주는 순서대로, 스위트가
한 번씩 실행됩니다. 순환마다 각 항목이 대입의 표준 규칙 (대입문 을 보
세요) 으로 타깃 목록에 대입된 다음, 스위트가 실행됩니다. 항목들이 소진
되었을 때 (이터레이터가 "StopIteration" 예외를 일으킬 때나 빈 시퀀스인
경우는 즉시 발생합니다), the "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()" 는 파스칼의 "for i := a to b do" 의 효과를 흉내 내는데
적합한 정수의 이터레이터를 돌려줍니다; 예를 들어, "list(range(3))" 는
리스트 "[0, 1, 2]" 를 돌려줍니다.

참고:

  시퀀스가 루프에 의해 수정될 때는 미묘한 점이 있습니다 (이것은 오직
  가변 시퀀스에서만 일어납니다, 가령 리스트). 다음에 어떤 항목이 사용
  될지를 추적하는 내부 카운터가 사용되고, 각 이터레이션마다 증가합니다
  . 이 카운터가 시퀀스의 길이에 도달하면 루프가 종료됩니다. 이것은 만
  약 스위트가 시퀀스에서 현재 (또는 그 이전의) 항목을 삭제하면, 다음
  항목을 건너뛰게 된다는 뜻입니다 (다음 항목이 이미 다뤄진 현재 항목의
  인덱스를 갖게 되기 때문입니다). 마찬가지로, 스위트가 현재 항목 앞으
  로 시퀀스에 항목을 삽입하면, 현재 항목은 루프의 다음 순환에서 현재
  항목이 한 번 더 다뤄지게 됩니다. 이것은 고약한 버그로 이어질 수 있는
  데, 전체 시퀀스의 슬라이스로 임시 사본을 만듦으로써 피할 수 있습니다
  , 예를 들어

     for x in a[:]:
         if x < 0: a.remove(x)


8.4. "try" 문
=============

"try" 문은 문장 그룹에 대한 예외 처리기나 정리(cleanup) 코드 또는 그
둘 모두를 지정하는 데 사용됩니다.

   try_stmt  ::= try1_stmt | try2_stmt
   try1_stmt ::= "try" ":" suite
                 ("except" [expression ["as" identifier]] ":" suite)+
                 ["else" ":" suite]
                 ["finally" ":" suite]
   try2_stmt ::= "try" ":" suite
                 "finally" ":" suite

"except" 절(들)은 하나나 그 이상의 예외 처리기를 지정합니다. "try" 절
에서 예외가 발생하지 않으면 아무런 예외 처리기도 실행되지 않습니다.
"try" 스위트에서 예외가 발생할 때, 예외 처리기 검색이 시작됩니다. 이
검색은 그 예외에 매치되는 것을 발견할 때까지 except 절을 차례대로 들여
다봅니다. 표현식이 없는 except 절이 있다면 가장 마지막에 와야 합니다;
모든 예외와 매치됩니다. 표현식이 있는 except 절의 경우, 표현식의 값을
구하고, 결과 객체가 예외와 "호환" 되면 그 절이 예외에 매치됩니다. 객체
는 예외 객체의 클래스나 베이스 클래스일 때, 또는 예외와 호환되는 항목
을 포함한 튜플일 때 예외와 호환됩니다.

except 절 중 어느 것도 예외와 매치되지 않으면, 예외 처리기 검색은 둘러
싼 코드와 호출 스택에서 계속됩니다. [1]

만약 except 절의 헤더에 있는 표현식의 값을 구할 때 예외가 발생하면, 원
래의 처리기 검색은 취소되고 둘러싼 코드와 호출 스택에서 새 예외에 대해
검사가 시작됩니다 ("try" 문 전체가 예외를 일으킨 것으로 취급됩니다).

매치되는 except 절이 발견되면, 예외는 그 except 절에 있는 "as" 키워드
(가 있다면) 뒤에 지정된 타깃에 대입되고, except 절의 스위트가 실행됩니
다. 모든 except 절은 실행 가능한 블록을 가져야 합니다. 블록의 끝에 도
달하면, try 문 전체의 뒤에서 일반적인 실행이 계속됩니다. (이것은 같은
예외에 대해 두 개의 중첩된 처리기가 있고, 예외가 안쪽 처리기의 try 절
에서 발생했다면, 바깥 처리기는 예외를 처리하지 않게 된다는 뜻이 됩니다
.)

예외가 "as target" 을 사용해서 대입될 때, except 절 끝에서 삭제됩니다.
이것은 마치

   except E as N:
       foo

가 이렇게 변환되는 것과 같습니다

   except E as N:
       try:
           foo
       finally:
           del N

이것은 except 절 후에 참조하려면 예외를 다른 이름에 대입해야 한다는 뜻
입니다. 예외를 제거하는 이유는, 그것에 첨부된 트레이스백으로 인해, 스
택 프레임과 참조 순환을 형성해서 다음 가비지 수거가 일어나기 전까지 그
프레임의 모든 지역 변수들을 잡아두기 때문입니다.

except 절의 스위트가 실행되기 전에, 예외의 상세 내용이 "sys" 모듈에 저
장되는데, "sys.exc_info()" 를 통해 액세스할 수 있습니다.
"sys.exc_info()" 는 예외 클래스, 예외 인스턴스, 예외가 프로그램의 어디
에서 발생했는지를 알려주는 트레이스백 객체 (표준형 계층 를 보세요) 로
이루어진 3-튜플을 돌려줍니다. "sys.exc_info()" 값들은 예외를 처리한 함
수로부터 복귀할 때 이전 값으로 복구됩니다.

생략 가능한 "else" 절은 제어 흐름이 "try" 스위트를 빠져나가고, 예외가
발생하지 않았고, "return", "continue" 또는 "break" 문이 실행되지 않으
면 실행됩니다. "else" 절에서 발생하는 예외는 앞에 나오는 "except" 절에
서 처리되지 않습니다.

"finally" 가 있으면, '정리(cleanup)' 처리기를 지정합니다. "except" 와
"else" 절을 포함해서, 먼저 "try" 절이 실행됩니다. 이 절들의 어디에서건
예외가 일어나면, 예외는 임시 저장됩니다. "finally" 절이 실행됩니다. 만
약 저장된 예외가 있으면, "finally" 절의 끝에서 다시 발생시킨다.
"finally" 절이 다른 예외를 일으키면, 저장된 예외는 새 예외의 컨텍스트
(context) 로 설정됩니다. "finally" 절이 "return" 이나 "break" 문을 실
행하면, 저장된 예외는 버립니다.

   >>> def f():
   ...     try:
   ...         1/0
   ...     finally:
   ...         return 42
   ...
   >>> f()
   42

"finally" 절을 실행하는 동안 예외 정보는 프로그램에 제공되지 않습니다.

"try"..."finally" 문의 "try" 스위트에서 "return", "break", "continue"
문이 실행될 때, "finally" 절도 '나가는 길에' 실행됩니다. "finally" 절
에서는 "continue" 문을 사용할 수 없습니다. (그 이유는 현재 구현에 있는
문제 때문입니다 --- 이 제약은 미래에 제거될 수 있습니다).

함수의 반환 값은 마지막에 실행된 "return" 문으로 결정됩니다. "finally"
절이 항상 실행되기 때문에, "finally" 절에서 실행되는 "return" 문이 항
상 마지막에 실행되는 것이 됩니다:

   >>> def foo():
   ...     try:
   ...         return 'try'
   ...     finally:
   ...         return 'finally'
   ...
   >>> foo()
   'finally'

예외에 관한 추가의 정보는 예외 섹션에서 찾을 수 있고, 예외를 일으키기
위해 "raise" 문을 사용하는 것에 관한 정보는 raise 문 섹션에서 찾을 수
있습니다.


8.5. "with" 문
==============

"with" 문은 블록의 실행을 컨텍스트 관리자 (with 문 컨텍스트 관리자 섹
션을 보세요) 가 정의한 메서드들로 감싸는 데 사용됩니다. 이것은 흔한
"try"..."except"..."finally" 사용 패턴을 편리하게 재사용할 수 있도록
캡슐화할 수 있도록 합니다.

   with_stmt ::= "with" with_item ("," with_item)* ":" suite
   with_item ::= expression ["as" target]

하나의 "item" 을 사용하는 "with" 문의 실행은 다음과 같이 진행됩니다:

1. 컨텍스트 관리자를 얻기 위해 컨텍스트 표현식 ("with_item" 에 주어진
   expression) 의 값을 구합니다.

2. 나중에 사용하기 위해 컨텍스트 관리자의 "__exit__()" 가 로드됩니다.

3. 컨텍스트 관리자의 "__enter__()" 메서드를 호출합니다.

4. "with" 문에 타깃이 포함되었으면, 그것에 "__enter__()" 의 반환 값을
   대입합니다.

   참고:

     "with" 문은 "__enter__()" 메서드가 에러 없이 돌아왔을 때,
     "__exit__()" 가 항상 호출됨을 보장합니다. 그래서, 타깃에 대입하는
     동안 에러가 발생하면, 스위트 안에서 에러가 발생한 것과 같이 취급
     됩니다. 아래의 6단계를 보세요.

5. 스위트가 실행됩니다.

6. 컨텍스트 관리자의 "__exit__()" 메서드를 호출합니다. 예외가 스위트를
   종료되도록 만들었다면, 그것의 형, 값, 트레이스백이 "__exit__()" 의
   인자로 전달됩니다. 그렇지 않으면 세 개의 "None" 이 인자로 공급됩니
   다.

   스위트가 예외 때문에 종료되었고, "__exit__()" 메서드의 반환 값이 거
   짓이면, 그 예외를 다시 일으킨다. 반환 값이 참이면, 예외를 억누르고,
   "with" 문 뒤에 오는 문장으로 실행을 계속합니다.

   스위트가 예외 이외의 이유로 종료되면, "__exit__()" 의 반환 값은 무
   시되고, 해당 종료의 종류에 맞는 위치에서 실행을 계속합니다.

하나 보다 많은 항목을 주면, 컨텍스트 관리자는 "with" 문이 중첩된 것처
럼 진행합니다:

   with A() as a, B() as b:
       suite

는 다음과 동등합니다

   with A() as a:
       with B() as b:
           suite

버전 3.1에서 변경: 다중 컨텍스트 표현식의 지원

더 보기:

  **PEP 343** - "with" 문
     파이썬 "with" 문의 규격, 배경, 예.


8.6. 함수 정의
==============

함수 정의는 사용자 정의 함수 객체 (표준형 계층 섹션을 보세요) 를 정의
합니다:

   funcdef                 ::= [decorators] "def" funcname "(" [parameter_list] ")"
               ["->" expression] ":" suite
   decorators              ::= decorator+
   decorator               ::= "@" dotted_name ["(" [argument_list [","]] ")"] NEWLINE
   dotted_name             ::= identifier ("." identifier)*
   parameter_list          ::= defparameter ("," defparameter)* ["," [parameter_list_starargs]]
                      | parameter_list_starargs
   parameter_list_starargs ::= "*" [parameter] ("," defparameter)* ["," ["**" parameter [","]]]
                               | "**" parameter [","]
   parameter               ::= identifier [":" expression]
   defparameter            ::= parameter ["=" expression]
   funcname                ::= identifier

함수 정의는 실행할 수 있는 문장입니다. 실행하면 현재 지역 이름 공간의
함수 이름을 함수 객체 (함수의 실행 가능한 코드를 둘러싼 래퍼
(wrapper)). 이 함수 객체는 현재의 이름 공간에 대한 참조를 포함하는데,
함수가 호출될 때 전역 이름 공간으로 사용됩니다.

함수 정의는 함수의 바디를 실행하지 않습니다. 함수가 호출될 때 실행됩니
다. [2]

함수 정의는 하나나 그 이상의 *데코레이터* 표현식으로 감싸질 수 있습니
다. 데코레이터 표현식은 함수가 정의될 때, 함수 정의를 포함하는 스코프
에서 값을 구합니다. 그 결과는 콜러블이어야 하는데, 함수 객체만을 인자
로 사용해서 호출됩니다. 반환 값이 함수 객체 대신 함수의 이름에 연결됩
니다. 여러 개의 데코레이터는 중첩되는 방식으로 적용됩니다. 예를 들어,
다음과 같은 코드

   @f1(arg)
   @f2
   def func(): pass

는 대략 다음과 동등합니다

   def func(): pass
   func = f1(arg)(f2(func))

원래의 함수가 임시로 이름 "func" 에 연결되지 않는다는 점만 다릅니다.

하나나 그 이상의 *매개변수* 들이 *parameter* "=" *expression* 형태를
가질 때, 함수가 "기본 매개변수 값"을 갖는다고 말합니다. 기본값이 있는
매개변수의 경우, 호출할 때 대응하는 *인자* 를 생략할 수 있고, 그럴 때
매개변수의 기본값이 적용됩니다. 만약 매개변수가 기본값을 가지면, ""*""
까지 그 뒤를 따르는 모든 매개변수도 기본값을 가져야 합니다 --- 이것은
문법 규칙에서 표현되지 않는 문법적 제약입니다.

**함수 정의가 실행될 때, 기본 매개변수 값은 왼쪽에서 오른쪽으로 값이
구해집니다.** 이것은 표현식이 함수가 정의될 때 한 번 값이 구해지고, 호
출마다 같은 "미리 계산된" 값이 사용된다는 것을 뜻합니다. 이것을 이해하
는 것은 특히 기본값이 리스트나 딕셔너리와 같은 가변 객체일 때 중요합니
다: 만약 함수가 그 객체를 수정하면 (가령, 리스트에 항목을 추가합니다),
그 결과 기본값이 수정됩니다. 이것은 일반적으로 의도하고 있는 것이 아니
다. 이 문제를 회피하는 방법은 기본값으로 "None" 을 사용하고, 함수 바디
에서 명시적으로 검사하는 것입니다, 예를 들어:

   def whats_on_the_telly(penguin=None):
       if penguin is None:
           penguin = []
       penguin.append("property of the zoo")
       return penguin

함수 호출의 의미는 섹션 호출 에서 더 자세히 설명됩니다. 함수 호출은 항
상 매개변수 목록에서 언급하는 모든 매개변수에 값을 대입하는데, 위치 인
자들에서 올 수도, 키워드 인자들에서 올 수도, 기본값에서 올 수도 있습니
다. ""*identifier"" 형태가 존재하면, 남는 위치 매개변수들을 받는 튜플
로 초기화됩니다. 기본값은 빈 튜플입니다. ""**identifier"" 형태가 존재
하면, 남는 키워드 인자들을 받는 순서 있는 매핑으로 초기화됩니다. 기본
값은 빈 매핑입니다. ""*"" 나 ""*identifier"" 뒤에 오는 매개변수들은 키
워드 전용 매개변수들이고, 키워드 인자로만 전달될 수 있습니다.

매개변수들은 매개변수 이름 뒤에 오는 "": expression"" 형태의 *어노테이
션*을 가질 수 있습니다. 모든 매개변수는 어노테이션을 가질 수 있는데,
"*identifier" 나 "**identifier" 형태조차 그렇습니다. 함수는 매개변수
목록 뒤에 오는 ""-> expression"" 형태의 반환("return") 어노테이션을 가
질 수 있습니다. 이 어노테이션들은 올바른 파이썬 표현식이면 어떤 것이건
될 수 있습니다. 어노테이션의 존재는 함수의 의미를 바꾸지 않습니다. 어
노테이션 값들은 함수 객체의 "__annotations__" 어트리뷰트에서 매개변수
의 이름을 키로 하는 딕셔너리의 값으로 제공됩니다. "__future__" 에서
"annotations" 을 임포트하면, 지연된 평가가 활성화되어 어노테이션은 실
행시간에 문자열로 보존됩니다. 그렇지 않으면 함수 정의가 실행될 때 평가
됩니다. 이 경우 어노테이션은 소스 코드에 나오는 순서와 다른 순서로 평
가될 수 있습니다.

표현식에서 즉시 사용하기 위해, 이름 없는 함수(이름에 연결되지 않은 함
수)를 만드는 것도 가능합니다. 이것은 람다 표현식을 사용하는데, 람다
(Lambdas) 섹션에서 설명합니다. 람다 표현식은 단순화된 함수 정의를 위한
줄임 표현에 지나지 않는다는 것에 주의하세요; ""def"" 문장에서 정의된
함수는 람다 표현식으로 정의된 함수처럼 전달되거나 다른 이름에 대입될
수 있습니다. 여러 개의 문장을 실행하는 것과 어노테이션을 허락하기 때문
에, ""def"" 형태가 사실 더 강력합니다.

**프로그래머 유의 사항:** 함수는 퍼스트 클래스(first-class) 객체다. 함
수 정의 안에서 실행되는 ""def"" 문은 돌려주거나 전달할 수 있는 지역 함
수를 정의합니다. 중첩된 함수에서 사용되는 자유 변수들은 그 def 를 포함
하는 함수의 지역 변수들을 액세스할 수 있습니다. 더 자세한 내용은 이름
과 연결(binding) 섹션을 보세요.

더 보기:

  **PEP 3107** - 함수 어노테이션
     함수 어노테이션의 최초 규격.

  **PEP 484** - 형 힌트
     어노테이션에 대한 표준 의미 정의: 형 힌트.

  **PEP 526** - 변수 어노테이션 문법
     클래스 변수 및 인스턴스 변수를 포함하는 변수 선언에 형 힌트를 줄
     수 있는 기능

  **PEP 563** - 어노테이션의 지연된 평가
     즉시 평가하는 대신 실행시간에 어노테이션을 문자열 형식으로 보존하
     여 어노테이션 내에서의 전방 참조를 지원합니다.


8.7. 클래스 정의
================

클래스 정의는 클래스 객체(표준형 계층 섹션을 보세요)를 정의합니다:

   classdef    ::= [decorators] "class" classname [inheritance] ":" suite
   inheritance ::= "(" [argument_list] ")"
   classname   ::= identifier

클래스 정의는 실행 가능한 문장입니다. 계승(inheritance) 목록은 보통 베
이스 클래스들의 목록을 제공하는데 (더 고급 사용에 대해서는 메타 클래스
를 보세요), 목록의 각 항목은 값을 구할 때 서브클래싱을 허락하는 클래스
객체가 되어야 합니다. 계승 목록이 없는 클래스는, 기본적으로, 베이스 클
래스 "object" 를 계승합니다; 그래서

   class Foo:
       pass

는 다음과 동등합니다

   class Foo(object):
       pass

클래스의 스위트는 새로 만들어진 지역 이름 공간과 원래의 전역 이름 공간
을 사용하는 새 실행 프레임 (이름과 연결(binding) 을 보세요)에서 실행됩
니다. (보통, 스위트는 대부분 함수 정의들을 포함합니다.) 클래스의 스위
트가 실행을 마치면, 실행 프레임은 파기하지만, 그것의 지역 이름 공간은
보존합니다. [3] 그런 다음, 계승 목록을 베이스 클래스들로, 보존된 지역
이름 공간을 어트리뷰트 딕셔너리로 사용해서 새 클래스 객체를 만듭니다.
클래스의 이름은 원래의 지역 이름 공간에서 이 클래스 객체와 연결됩니다.

클래스 바디에서 어트리뷰트가 정의되는 순서는, 새 클래스의 "__dict__"
에 보존됩니다. 이것은 클래스가 만들어진 직후에, 정의 문법을 사용해서
정의되는 클래스들에서만 신뢰할 수 있다는 것에 주의해야 합니다.

클래스 생성은 메타 클래스 를 사용해서 심하게 커스터마이즈할 수 있습니
다.

클래스 역시 함수를 데코레이팅할 때처럼 테코레이트할 수 있습니다,

   @f1(arg)
   @f2
   class Foo: pass

는 대략 다음과 동등합니다

   class Foo: pass
   Foo = f1(arg)(f2(Foo))

데코레이터 표현식의 값을 구하는 규칙은 함수 데코레이터와 같습니다. 그
런 다음 그 결과가 클래스 이름에 연결됩니다.

**프로그래머 유의 사항:** 클래스 정의에서 정의되는 변수들은 클래스 어
트리뷰트입니다; 이것들은 인스턴스 간에 공유됩니다. 인스턴스 어트리뷰트
는 메서드에서 "self.name = value" 로 설정될 수 있습니다. 클래스와 인스
턴스 어트리뷰트 모두 ""self.name"" 표기법으로 액세스할 수 있고, 이런
식으로 액세스할 때 인스턴스 어트리뷰트는 같은 이름의 클래스 어트리뷰트
를 가립니다. 클래스 어트리뷰트는 인스턴스 어트리뷰트의 기본값으로 사용
될 수 있지만, 가변 값을 사용하는 것은 예상하지 않은 결과를 줄 수 있습
니다. 디스크립터 를 다른 구현 상세를 갖는 인스턴스 변수를 만드는데 사
용할 수 있습니다.

더 보기:

  **PEP 3115** - 파이썬 3000의 메타 클래스
     메타 클래스 선언을 현재 문법으로 변경하고, 메타 클래스가 있는 클
     래스를 구성하는 방법의 의미를 변경하는 제안.

  **PEP 3129** - 클래스 데코레이터
     클래스 데코레이터를 추가하는 제안. 함수와 메서드 데코레이터는
     **PEP 318**에서 도입되었습니다.


8.8. 코루틴
===========

버전 3.5에 추가.


8.8.1. 코루틴 함수 정의
-----------------------

   async_funcdef ::= [decorators] "async" "def" funcname "(" [parameter_list] ")"
                     ["->" expression] ":" suite

파이썬 코루틴의 실행은 여러 지점에서 일시 중지되거나 재개될 수 있습니
다 (*코루틴* 을 보세요.). 코루틴의 바디 안에서, "await" 와 "async" 식
별자는 예약 키워드가 됩니다; 어웨이트("await") 표현식, "async for",
"async with" 는 코루틴 바디에서만 사용할 수 있습니다.

"async def" 문법으로 정의된 함수는 항상 코루틴 함수인데, "await" 나
"async" 키워드를 포함하지 않는 경우도 그렇습니다.

코루틴 함수의 바디 안에서 "yield from" 표현식을 사용하는 것은
"SyntaxError" 입니다.

코루틴 함수의 예:

   async def func(param1, param2):
       do_stuff()
       await some_coroutine()


8.8.2. "async for" 문
---------------------

   async_for_stmt ::= "async" for_stmt

*비동기 이터러블* 은 *iter* 구현에서 비동기 코드를 호출할 수 있고, *비
동기 이터레이터* 는 *next* 메서드에서 비동기 코드를 호출할 수 있습니다
.

"async for" 문은 비동기 이터레이터에 대한 편리한 이터레이션을 허락합니
다.

다음과 같은 코드는:

   async for TARGET in ITER:
       BLOCK
   else:
       BLOCK2

의미상으로 다음과 동등합니다:

   iter = (ITER)
   iter = type(iter).__aiter__(iter)
   running = True
   while running:
       try:
           TARGET = await type(iter).__anext__(iter)
       except StopAsyncIteration:
           running = False
       else:
           BLOCK
   else:
       BLOCK2

더 자세한 내용은 "__aiter__()" 를 "__anext__()" 보면 됩니다.

코루틴 함수의 바디 밖에서 "async for" 문을 사용하는 것은 "SyntaxError"
입니다.


8.8.3. "async with" 문
----------------------

   async_with_stmt ::= "async" with_stmt

*비동기 컨텍스트 관리자* 는 *enter* 와 *exit* 메서드에서 실행을 일시
중지할 수 있는 *컨텍스트 관리자* 입니다.

다음과 같은 코드는:

   async with EXPR as VAR:
       BLOCK

의미상으로 다음과 동등합니다:

   mgr = (EXPR)
   aexit = type(mgr).__aexit__
   aenter = type(mgr).__aenter__(mgr)

   VAR = await aenter
   try:
       BLOCK
   except:
       if not await aexit(mgr, *sys.exc_info()):
           raise
   else:
       await aexit(mgr, None, None, None)

더 자세한 내용은 "__aenter__()" 와 "__aexit__()" 를 보면 됩니다.

코루틴 함수의 바디 밖에서 "async with" 문을 사용하는 것은
"SyntaxError" 입니다.

더 보기:

  **PEP 492** - async 와 await 문법을 사용하는 코루틴
     코루틴을 파이썬에서 적절한 독립적인 개념으로 만들고, 문법 지원을
     추가한 제안.

-[ 각주 ]-

[1] 다른 예외를 일으키는 "finally" 절이 있지 않은 한 예외는 호출 스택
    으로 퍼집니다. 그 새 예외는 예전의 것을 잃어버리게 만듭니다.

[2] 함수 바디의 첫 번째 문장으로 등장하는 문자열 리터럴은 함수의
    "__doc__" 어트리뷰트로 변환되어 함수의 *독스트링* 이 됩니다.

[3] 클래스 바디의 첫 번째 문장으로 등장하는 문자열 리터럴은 그 이름 공
    간의 "__doc__" 항목으로 변환되어 클래스의 *독스트링* 이 됩니다.
