# 7. 단순문(Simple statements)

단순문은 하나의 논리적인 줄 안에 구성됩니다. 여러 개의 단순문이 세미콜론으로 분리되어 하나의 줄에 나올 수 있습니다. 단순문의 문법은 이렇습니다:

    simple_stmt: expression_stmt
                 | assert_stmt
                 | assignment_stmt
                 | augmented_assignment_stmt
                 | annotated_assignment_stmt
                 | pass_stmt
                 | del_stmt
                 | return_stmt
                 | yield_stmt
                 | raise_stmt
                 | break_stmt
                 | continue_stmt
                 | import_stmt
                 | future_stmt
                 | global_stmt
                 | nonlocal_stmt
                 | type_stmt

## 7.1. 표현식 문

표현식 문은 값을 계산하고 출력하거나, (보통) 프로시저(procedure) (의미 없는 결과를 돌려주는 함수; 파이썬에서 프로시저는 `None` 값을 돌려줍니다)를 호출하기 위해 (대부분 대화형으로) 사용됩니다. 표현식 문의 다른 사용도 허락되고 때때로 쓸모가 있습니다.

    expression_stmt: starred_expression

표현식 문은 (하나의 표현식일 수 있는) 표현식 목록의 값을 구합니다.

대화형 모드에서, 값이 `None` 이 아니면, 내장 `repr()` 함수를 사용해 문자열로 변환되고, 그렇게 나온 문자열을 별도의 줄에 표준 출력으로 보냅니다 (결과가 `None` 일 때는 그렇지 않아서, 프로시저 호출은 어떤 출력도 만들지 않습니다.),

## 7.2. 대입문

대입문은 이름을 값에 (재)연결하고 가변 객체의 어트리뷰트나 항목들을 수정합니다.

    assignment_stmt: (target_list "=")+ (starred_expression | yield_expression)
    target_list:     target ("," target)* [","]
    target:          identifier
                     | "(" [target_list] ")"
                     | "[" [target_list] "]"
                     | attributeref
                     | subscription
                     | "*" target

(See section 프라이머리 for the syntax definitions for attributeref and subscription.)

대입문은 표현식 목록 (이것이 하나의 표현식일 수도, 쉼표로 분리된 목록일 수도 있는데, 후자의 경우는 튜플이 만들어진다는 것을 기억하십시오) 의 값을 구하고, 왼쪽에서 오른쪽으로, 하나의 결과 객체를 타깃 목록의 각각에 대입합니다.

Assignment is defined recursively depending on the form of the target (list). When a target is part of a mutable object (an attribute reference or subscription), the mutable object must ultimately perform the assignment and decide about its validity, and may raise an exception if the assignment is unacceptable. The rules observed by various types and the exceptions raised are given with the definition of the object types (see section 표준형 계층).

객체를 타깃 목록, 괄호나 대괄호로 둘러싸일 수 있는데 생략할 수 있습니다, 에 대입하는 것은 다음과 같이 재귀적으로 정의됩니다.

- 타깃 목록이 (선택적으로 괄호에 들어있는) 뒤따르는 쉼표가 없는 하나의 타깃이면 객체는 타깃에 대입됩니다.

- 그렇지 않으면:

  - 타깃 목록이 애스터리스크(asterisk)를 앞에 붙인 타깃, “스타드(starred)” 타깃이라고 불립니다, 하나를 포함하면: 객체는 적어도 타깃 목록에 나오는 타깃의 수보다 하나 작은 개수의 항목을 제공하는 이터러블이어야 합니다. 이터러블의 처음 항목들은, 왼쪽에서 오른쪽으로, 스타드 타깃 앞에 나오는 타깃들에 대입됩니다. 이터러블의 마지막 항목들은 스타드 타깃 뒤에 나오는 타깃들에 대입됩니다. 이터러블의 나머지 항목들로 구성된 리스트가 스타드 타깃에 대입됩니다 (이 리스트는 비어있을 수 있습니다).

  - 그렇지 않으면: 객체는 타깃 목록에 나오는 타깃의 수와 같은 수의 항목들을 제공하는 이터러블이어야 하고, 항목들은, 왼쪽에서 오른쪽으로, 대응하는 타깃들에 대입됩니다.

하나의 타깃에 대한 객체의 대입은 다음과 같이 재귀적으로 정의됩니다.

- 타깃이 식별자 (이름) 면:

  - 그 이름이 현재 코드 블록에 있는 `global` 나 `nonlocal` 문에 등장하지 않으면: 그 이름은 현재 지역 이름 공간에서 객체에 연결됩니다.

  - 그렇지 않으면: 그 이름은 각각 전역 이름 공간이나 `nonlocal` 에 의해 결정되는 외부 이름 공간에서 객체에 연결됩니다.

  그 이름이 이미 연결되어 있으면 재연결됩니다. 이것은 기존에 연결되어 있던 객체의 참조 횟수가 0이 되도록 만들어서, 객체가 점유하던 메모리가 반납되고 파괴자(destructor) (갖고 있다면) 가 호출되도록 만들 수 있습니다.

- 타깃이 어트리뷰트 참조면: 참조의 프라이머리 표현식의 값을 구합니다. 이것은 대입 가능한 어트리뷰트를 가진 객체를 주어야 하는데, 그렇지 않으면 `TypeError` 가 일어납니다. 그에 그 객체에 주어진 어트리뷰트로 객체를 대입하도록 요청합니다; 대입을 수행할 수 없다면 예외 (보통 `AttributeError` 이지만, 꼭 그럴 필요는 없다) 를 일으킵니다.

  주의 사항: 객체가 클래스 인스턴스이고 어트리뷰트 참조가 대입 연산자의 양쪽에서 모두 등장하면, 우변(right-hand side) 표현식, `a.x` 는 인스턴스 어트리뷰트나 (인스턴스 어트리뷰트가 없다면) 클래스 어트리뷰트를 액세스할 수 있습니다. 좌변(left-hand side) 타깃 `a.x` 는 항상 필요하면 만들어서라도 항상 인스턴스 어트리뷰트를 설정합니다. 그래서, 두 `a.x` 가 같은 어트리뷰트를 가리키는 것은 필요조건이 아닙니다: 우변 표현식이 클래스 어트리뷰트를 가리킨다면, 좌변은 대입의 타깃으로 새 인스턴스 어트리뷰트를 만듭니다:

      class Cls:
          x = 3             # 클래스 변수
      inst = Cls()
      inst.x = inst.x + 1   # inst.x 에 4 를 쓰고 Cls.x 는 3 으로 남겨둡니다

  이 설명이 `property()` 로 만들어진 프로퍼티(property)와 같은 디스크립터 어트리뷰트에 적용될 필요는 없습니다.

- If the target is a subscription: The primary expression in the reference is evaluated. Next, the subscript expression is evaluated. Then, the primary’s `__setitem__()` method is called with two arguments: the subscript and the assigned object.

  Typically, `__setitem__()` is defined on mutable sequence objects (such as lists) and mapping objects (such as dictionaries), and behaves as follows.

  프라이머리가 (리스트 같은) 가변 시퀀스 객체면, 서브 스크립트는 정수가 나와야 합니다. 음수면, 시퀀스의 길이가 더해집니다. 결괏값은 시퀀스의 길이보다 작은 음이 아닌 정수여야 하고, 시퀀스에 그 인덱스를 가진 항목에 객체를 대입하라고 요청합니다. 인덱스가 범위를 벗어나면, `IndexError` 를 일으킵니다 (서브 스크립트 된 시퀀스에 대한 대입은 리스트에 새 항목을 추가할 수 없습니다).

  프라이머리가 (딕셔너리 같은) 매핑 객체면, 서브 스크립트는 매핑의 키 형과 호환되는 형이어야 하고, 매핑에 그 서브 스크립트를 객체에 매핑하는 키/값 쌍을 만들도록 요청합니다. 이때 같은 킷값을 갖는 기존의 키/값 쌍을 대체할 수도 있고, (같은 값의 키가 존재하지 않는 경우) 새 키/값 쌍을 삽입할 수도 있습니다.

  If the target is a slicing: The primary expression should evaluate to a mutable sequence object (such as a list). The assigned object should be iterable. The slicing’s lower and upper bounds should be integers; if they are `None` (or not present), the defaults are zero and the sequence’s length. If either bound is negative, the sequence’s length is added to it. The resulting bounds are clipped to lie between zero and the sequence’s length, inclusive. Finally, the sequence object is asked to replace the slice with the items of the assigned sequence. The length of the slice may be different from the length of the assigned sequence, thus changing the length of the target sequence, if the target sequence allows it.

설사 대입의 정의가 좌변과 우변 간의 중첩이 ‘동시적(simultaneous)’임을 (예를 들어, `a, b = b, a` 는 두 변수를 교환합니다) 암시해도, 대입되는 변수들의 컬렉션 안 에서의 중첩은 왼쪽에서 오른쪽으로 일어나서, 때로 혼동할 수 있는 결과를 낳습니다. 예를 들어, 다음과 같은 프로그램은 `[0, 2]` 를 인쇄합니다:

    x = [0, 1]
    i = 0
    i, x[i] = 1, 2         # i 가 갱신된 다음에, x[i] 가 갱신됩니다
    print(x)

더 보기

PEP 3132 - 확장 이터러블 언 패킹

  `*target` 기능에 대한 규격

### 7.2.1. 증분 대입문(Augmented assignment statements)

증분 대입문은 한 문장에서 이항 연산과 대입문을 합치는 것입니다:

    augmented_assignment_stmt: augtarget augop (expression_list | yield_expression)
    augtarget:                 identifier | attributeref | subscription
    augop:                     "+=" | "-=" | "*=" | "@=" | "/=" | "//=" | "%=" | "**="
                               | ">>=" | "<<=" | "&=" | "^=" | "|="

(마지막 세 기호의 문법 정의는 프라이머리 섹션을 보십시오.)

증분 대입은 타깃 (일반 대입문과는 달리 언 패킹이 될 수 없습니다) 과 표현식 목록의 값을 구하고, 둘을 피연산자로 삼아 대입의 형에 맞는 이항 연산을 수행한 후, 원래의 타깃에 그 결과를 대입합니다. 타깃은 오직 한 번만 값이 구해집니다.

`x += 1` 과 같은 증분 대입문은 `x = x + 1` 처럼 다시 쓸 수 있는데, 정확히 같은 효과는 아니지만 비슷한 결과를 줍니다. 증분 버전에서는, `x` 의 값을 오직 한 번만 구합니다. 또한, 가능할 때, 실제 연산은 제자리(in-place) 에서 수행되는데, 새 객체를 만들고 그것을 타깃에 대입하기보다는, 예전 객체를 수정한다는 의미입니다.

일반 대입과는 달리, 증분 대입은 우변의 값을 구하기 이전에 좌변의 값을 구합니다. 예를 들어, `a[i] += f(x)` 는 처음에 `a[i]` 를 조회한 다음, `f(x)` 의 값을 구하고, 덧셈을 수행하고, 마지막으로 그 결과를 `a[i]` 에 다시 씁니다.

하나의 문장에서 튜플과 다중 타깃으로 대입하는 것을 예외로 하면, 증분 대입문에 의한 대입은 일반 대입과 같은 방법으로 처리됩니다. 마찬가지로, 제자리 동작의 가능성을 예외로 하면, 증분 대입 때문에 수행되는 이진 연산은 일반 이진 연산과 같습니다.

어트리뷰트 참조인 타깃의 경우, 일반 대입처럼 클래스와 인스턴스 어트리뷰트에 관한 경고 가 적용됩니다.

### 7.2.2. 어노테이트된 대입문(Annotated assignment statements)

어노테이션 대입은, 한 문장에서, 변수나 어트리뷰트 어노테이션과 생략할 수 있는 대입문을 합치는 것입니다.

    annotated_assignment_stmt: augtarget ":" expression
                               ["=" (starred_expression | yield_expression)]

일반 대입문 과의 차이점은 오직 하나의 타깃만 허락된다는 것입니다.

The assignment target is considered “simple” if it consists of a single name that is not enclosed in parentheses. For simple assignment targets, if in class or module scope, the annotations are gathered in a lazily evaluated annotation scope. The annotations can be evaluated using the `__annotations__` attribute of a class or module, or using the facilities in the `annotationlib` module.

If the assignment target is not simple (an attribute, subscript node, or parenthesized name), the annotation is never evaluated.

이름이 함수 스코프에서 어노테이트되면, 이 이름은 그 스코프에 지역적(local)입니다. 함수 스코프에서 어노테이션은 값이 구해지거나 저장되지 않습니다.

If the right hand side is present, an annotated assignment performs the actual assignment as if there was no annotation present. If the right hand side is not present for an expression target, then the interpreter evaluates the target except for the last `__setitem__()` or `__setattr__()` call.

더 보기

PEP 526 - 변수 어노테이션 문법

  주석을 통해 표현하는 대신, 변수(클래스 변수와 인스턴스 변수 포함)의 형을 어노테이트 하는 문법을 추가하는 제안.

PEP 484 - 형 힌트

  정적 분석 도구와 IDE에서 사용할 수 있는 형 어노테이션에 대한 표준 문법을 제공하기 위해 `typing` 모듈을 추가하는 제안.

버전 3.8에서 변경: 이제 어노테이트된 대입문은 일반 대입과 마찬가지로 우변에 같은 표현식을 허용합니다. 이전에는, (괄호 없는 튜플 표현식과 같은) 일부 표현식에서 문법 에러가 발생했습니다.

버전 3.14에서 변경: Annotations are now lazily evaluated in a separate annotation scope. If the assignment target is not simple, annotations are never evaluated.

## 7.3. `assert` 문

assert 문은 프로그램에 디버깅 어서션(debugging assertion)을 삽입하는 편리한 방법입니다:

    assert_stmt: "assert" expression ["," expression]

간단한 형태, `assert expression` 은 다음과 동등합니다

    if __debug__:
        if not expression: raise AssertionError

확장된 형태, `assert expression1, expression2` 는 다음과 동등합니다

    if __debug__:
        if not expression1: raise AssertionError(expression2)

이 동등성 들은 `__debug__` 과 `AssertionError` 가 같은 이름의 내장 변수들을 가리킨다고 가정합니다. 현재 구현에서, 내장 변수 `__debug__` 은 일반적인 상황에서 `True` 이고, 최적화가 요청되었을 때 (명령행 옵션 `-O`) `False` 입니다. 현재의 코드 생성기는 컴파일 시점에 최적화가 요청되면 `assert` 문을 위한 코드를 만들지 않습니다. 에러 메시지에 실패한 표현식의 소스 코드를 포함할 필요가 없음에 주의하십시오; 그것은 스택 트레이스의 일부로 출력됩니다.

`__debug__` 에 대한 대입은 허락되지 않습니다. 이 내장 변수의 값은 인터프리터가 시작할 때 결정됩니다.

## 7.4. `pass` 문

    pass_stmt: "pass"

`pass` 는 널(null) 연산입니다 — 실행될 때, 아무런 일도 일어나지 않습니다. 문법적으로 문장이 필요하기는 하지만 할 일은 없을 때, 자리를 채우는 용도로 쓸모가 있습니다, 예를 들어:

    def f(arg): pass    # (아직은) 아무것도 하지 않는 함수

    class C: pass       # (아직은) 메서드가 없는 클래스

## 7.5. `del` 문

    del_stmt: "del" target_list

삭제는 대입이 정의된 방식과 아주 비슷하게 재귀적으로 정의됩니다. 전체 세부 사항들을 나열하는 대신, 여기 몇 가지 힌트가 있습니다.

타깃 목록의 삭제는 각 타깃을 왼쪽에서 오른쪽으로 재귀적으로 삭제합니다.

Deletion of a name removes the binding of that name from the local or global namespace, depending on whether the name occurs in a `global` statement in the same code block. Trying to delete an unbound name raises a `NameError` exception.

Deletion of attribute references and subscriptions is passed to the primary object involved; deletion of a slicing is in general equivalent to assignment of an empty slice of the right type (but even this is determined by the sliced object).

버전 3.2에서 변경: 예전에는 이름이 중첩된 블록에서 자유 변수로 등장하는 경우 지역 이름 공간에서 삭제하는 것이 허락되지 않았습니다.

## 7.6. `return` 문

    return_stmt: "return" [expression_list]

`return` 은 문법적으로 클래스 정의에 중첩된 경우가 아니라, 함수 정의에만 중첩되어 나타날 수 있습니다.

표현식 목록이 있으면 값을 구하고, 그렇지 않으면 `None` 으로 치환됩니다.

`return` 은 표현식 목록 (또는 `None`)을 반환 값으로 해서, 현재의 함수 호출을 떠납니다.

`return` 이 `finally` 절을 가진 `try` 문에서 제어가 벗어나도록 만드는 경우, 함수로부터 진짜로 벗어나기 전에 그 `finally` 절이 실행됩니다.

제너레이터 함수에서, `return` 문은 제너레이터가 끝났음을 가리키고, `StopIteration` 예외를 일으킵니다. return 문에 제공되는 값은 (있다면) `StopIteration` 의 생성자에 인자로 전달되어 `StopIteration.value` 어트리뷰트가 됩니다.

비동기 제너레이터 함수에서, 빈 `return` 문은 비동기 제너레이터가 끝났음을 알리고, `StopAsyncIteration` 예외를 일으킵니다. 비동기 제너레이터 함수에서, 비어있지 않은 `return` 은 문법 에러입니다.

## 7.7. `yield` 문

    yield_stmt: yield_expression

`yield` 문은 yield 표현식 과 같은 의미가 있습니다. 동등한 yield 표현식에서 필요로 하는 괄호를 생략하기 위해 `yield` 문을 사용합니다. 예를 들어, yield 문

    yield <expr>
    yield from <expr>

은 다음과 같은 yield 표현식 문장들과 동등합니다

    (yield <expr>)
    (yield from <expr>)

yield 표현식과 문장은 제너레이터 함수를 정의할 때만 사용되고, 제너레이터 함수의 바디에서만 사용됩니다. 함수 정의가 일반 함수 대신 제너레이터 함수를 만들도록 하는 데는 `yield`를 사용하는 것만으로 충분합니다.

`yield` 의 뜻에 대한 전체 세부 사항들은 일드 표현식(Yield expressions) 섹션을 참고하면 됩니다.

## 7.8. `raise` 문

    raise_stmt: "raise" [expression ["from" expression]]

표현식이 주어지지 않으면, `raise` 는, 활성 예외라고도 부르는, 현재 처리 중인 예외를 다시 일으킵니다. 현재 활성 예외가 없다면, 이것이 에러라는 것을 알리기 위해 `RuntimeError` 예외를 일으킵니다.

그렇지 않으면, `raise` 는 예외 객체로, 첫 번째 표현식의 값을 구합니다. `BaseException` 의 서브 클래스나 인스턴스여야 합니다. 클래스면, 예외 인스턴스는 필요할 때 인자 없이 클래스의 인스턴스를 만들어서 사용됩니다.

예외의 형(type)은 예외 인스턴스의 클래스고, 값(value)은 인스턴스 자신입니다.

트레이스백 객체는 보통 예외가 일어날 때 자동으로 만들어지고 `__traceback__` 어트리뷰트로 첨부됩니다. 다음과 같이, `with_traceback()` 예외 메서드를 사용하면, 예외를 만들고 트레이스백을 직접 설정하는 것을 한 번에 할 수 있습니다 (같은 예외 인스턴스를 돌려주는데, 그 인자값으로 트레이스백을 설정해줍니다):

    raise Exception("foo occurred").with_traceback(tracebackobj)

`from` 절은 예외 연쇄(exception chaining)에 사용됩니다. 주어진다면, 두 번째 표현식(expression) 은 또 하나의 예외 클래스나 인스턴스여야 합니다. 두 번째 표현식이 예외 인스턴스면, 발생한 예외에 (쓰기 가능한) `__cause__` 어트리뷰트로 첨부됩니다. 표현식이 예외 클래스면, 클래스가 인스턴스화되어 만들어진 예외 인스턴스가 발생한 예외에 `__cause__` 어트리뷰트로 첨부됩니다. 발생한 예외가 처리되지 않으면, 두 예외가 모두 인쇄됩니다:

    >>> try:
    ...     print(1 / 0)
    ... except Exception as exc:
    ...     raise RuntimeError("Something bad happened") from exc
    ...
    Traceback (most recent call last):
      File "<stdin>", line 2, in <module>
        print(1 / 0)
              ~~^~~
    ZeroDivisionError: division by zero

    The above exception was the direct cause of the following exception:

    Traceback (most recent call last):
      File "<stdin>", line 4, in <module>
        raise RuntimeError("Something bad happened") from exc
    RuntimeError: Something bad happened

예외가 이미 처리되고 있을 때 새 예외가 발생하면 비슷한 메커니즘이 묵시적으로 적용됩니다. `except` 나 `finally` 절 또는 `with` 문이 사용될 때 예외가 처리될 수 있습니다. 앞선 예외가 새 예외의 `__context__` 어트리뷰트로 첨부됩니다:

    >>> try:
    ...     print(1 / 0)
    ... except:
    ...     raise RuntimeError("Something bad happened")
    ...
    Traceback (most recent call last):
      File "<stdin>", line 2, in <module>
        print(1 / 0)
              ~~^~~
    ZeroDivisionError: division by zero

    During handling of the above exception, another exception occurred:

    Traceback (most recent call last):
      File "<stdin>", line 4, in <module>
        raise RuntimeError("Something bad happened")
    RuntimeError: Something bad happened

예외 연쇄는 `from` 절에 `None` 을 지정해서 명시적으로 중지시킬 수 있습니다:

    >>> try:
    ...     print(1 / 0)
    ... except:
    ...     raise RuntimeError("Something bad happened") from None
    ...
    Traceback (most recent call last):
      File "<stdin>", line 4, in <module>
    RuntimeError: Something bad happened

예외에 대한 더 많은 정보를 예외 섹션에서 발견할 수 있고, 예외를 처리하는 것에 대한 정보는 try 문 섹션에 있습니다.

버전 3.3에서 변경: 이제 `raise X from Y` 에서 `Y` 로 `None` 이 허락됩니다.

예외 문맥(exception context)의 자동 출력을 제한할 수 있는 `__suppress_context__` 어트리뷰트를 추가했습니다.

버전 3.11에서 변경: If the traceback of the active exception is modified in an `except` clause, a subsequent `raise` statement re-raises the exception with the modified traceback. Previously, the exception was re-raised with the traceback it had when it was caught.

## 7.9. `break` 문

    break_stmt: "break"

`break` 는 문법적으로 `for` 나 `while` 루프에 중첩되어서만 나타날 수 있습니다. 하지만 그 루프 안의 함수나 클래스 정의에 중첩되지는 않습니다.

가장 가까이서 둘러싸고 있는 루프를 종료하고, 그 루프가 `else` 절을 갖고 있다면 건너뜁니다(skip).

`for` 루프가 `break` 로 종료되면, 루프 제어 타깃은 현재값을 유지합니다.

`break` 가 `finally` 절을 가 `try` 문에서 제어가 벗어나도록 만드는 경우, 루프로부터 진짜로 벗어나기 전에 그 `finally` 절이 실행됩니다.

## 7.10. `continue` 문

    continue_stmt: "continue"

`continue` 는 문법적으로 `for` 나 `while` 루프에 중첩되어서만 나타날 수 있습니다. 하지만 그 루프 안의 함수나 클래스 정의에 중첩되지는 않습니다. 가장 가까이서 둘러싸고 있는 루프가 다음 사이클로 넘어가도록 만듭니다.

`continue` 가 `finally` 절을 가진 `try` 문에서 제어가 벗어나도록 만드는 경우, 다음 루트 사이클을 시작하기 전에 그 `finally` 절이 실행됩니다.

## 7.11. 임포트(`import`) 문

    import_stmt:     ["lazy"] "import" module ["as" identifier] ("," module ["as" identifier])*
                     | ["lazy"] "from" relative_module "import" identifier ["as" identifier]
                     ("," identifier ["as" identifier])*
                     | ["lazy"] "from" relative_module "import" "(" identifier ["as" identifier]
                     ("," identifier ["as" identifier])* [","] ")"
                     | "from" relative_module "import" "*"
    module:          (identifier ".")* identifier
    relative_module: "."* module | "."+

(`from` 절이 없는) 기본 임포트 문은 두 단계로 실행됩니다:

1. 모듈을 찾고, 로드하고, 필요하면 초기화합니다

2. define a name or names in the current namespace for the scope where the `import` statement occurs, just as an assignment statement would (including `global` and `nonlocal` semantics).

문장이 (쉼표로 분리된) 여러 개의 절을 포함하면, 마치 각 절이 별도의 임포트 문에 의해 분리된 것처럼, 두 단계는 절마다 별도로 수행됩니다.

첫 번째 단계, 모듈을 찾고 로드하는 것의 세부 사항은 임포트 시스템 에 있는 섹션에서 아주 상세하게 설명하는데, 임포트될 수 있는 여러 종류의 패키지와 모듈들과 임포트 시스템을 커스터마이즈하는데 사용될 수 있는 모든 훅에 관해서도 설명하고 있습니다.

요청된 모듈이 성공적으로 읽어 들여지면, 세 가지 중 한 방법으로 지역 이름 공간에 소개됩니다:

- 모듈 이름 뒤에 `as` 가 오면, `as` 뒤에 오는 이름이 임포트된 모듈에 직접 연결됩니다.

- 다른 이름이 지정되지 않고, 임포트되는 모듈이 최상위 모듈이면, 모듈의 이름이 임포트되는 모듈에 대한 참조로 지역 이름 공간에 연결됩니다.

- 임포트되는 모듈이 최상이 모듈이 아니 라면, 그 모듈을 포함하는 최상위 패키지의 이름이 최상위 패키지에 대한 참조로 지역 이름 공간에 연결됩니다. 임포트된 모듈은 직접적이기보다는 완전히 정규화된 이름(full qualified name)을 통해 액세스 되어야 합니다.

`from` 형은 약간 더 복잡한 절차를 사용합니다:

1. `from` 절에 지정된 모듈을 찾고, 로드하고, 필요하면 초기화합니다

2. `import` 절에 지정된 식별자들 각각에 대해:

   1. 임포트된 모듈이 그 이름의 어트리뷰트를 가졌는지 검사합니다

   2. 없으면, 그 이름의 서브 모듈을 임포트하는 것을 시도한 다음 임포트된 모듈에서 그 어트리뷰트를 다시 검사합니다

   3. 어트리뷰트가 발견되지 않으면 `ImportError` 를 일으킵니다.

   4. otherwise, a reference to that value is stored in the current namespace, using the name in the `as` clause if it is present, otherwise using the attribute name

사용 예:

    import foo                 # foo 가 임포트되고 지역적으로 연결됩니다
    import foo.bar.baz         # foo, foo.bar, foo.bar.baz 가 임포트되고, foo 가 지역적으로 연결됩니다
    import foo.bar.baz as fbb  # foo, foo.bar, foo.bar.baz 가 임포트되고, foo.bar.baz 가 fbb 로 연결됩니다
    from foo.bar import baz    # foo, foo.bar, foo.bar.baz 가 임포트되고, foo.bar.baz 가 baz 로 연결됩니다
    from foo import attr       # foo 가 임포트되고 foo.attr 이 attr 로 연결됩니다

식별자들의 목록을 스타 (`'*'`) 로 바꾸면, 모듈에 정의된 모든 공개 이름들이 `import` 문이 등장한 스코프의 지역 이름 공간에 연결됩니다.

The public names defined by a module are determined by checking the module’s namespace for a variable named `__all__`; if defined, it must be a sequence of strings which are names defined or imported by that module. Names containing non-ASCII characters must be in the normalization form NFKC; see Non-ASCII characters in names for details. The names given in `__all__` are all considered public and are required to exist. If `__all__` is not defined, the set of public names includes all names found in the module’s namespace which do not begin with an underscore character (`'_'`). `__all__` should contain the entire public API. It is intended to avoid accidentally exporting items that are not part of the API (such as library modules which were imported and used within the module).

임포트의 와일드카드 형태 — `from module import *` — 는 모듈 수준에서만 허락됩니다. 클래스나 함수 정의에서 사용하려는 시도는 `SyntaxError` 를 일으킵니다.

임포트할 모듈을 지정할 때 모듈의 절대 이름(absolute name)을 지정할 필요는 없습니다. 모듈이나 패키지가 다른 패키지 안에 포함될 때, 같은 상위 패키지 내에서는 그 패키지 이름을 언급할 필요 없이 상대 임포트(relative import)를 할 수 있습니다. `from` 뒤에 지정되는 패키지나 모듈 앞에 붙이는 점으로, 정확한 이름을 지정하지 않고도 현재 패키지 계층을 얼마나 거슬러 올라가야 하는지 지정할 수 있습니다. 하나의 점은 이 임포트를 하는 모듈이 존재하는 현재 패키지를 뜻합니다. 두 개의 점은 한 패키지 수준을 거슬러 올라가는 것을 뜻합니다. 세 개의 점은 두 개의 수준을, 등등입니다. 그래서 `pkg` 패키지에 있는 모듈에서 `from . import mod` 를 실행하면, `pkg.mod` 를 임포트하게 됩니다. `pkg.subpkg1` 안에서 `from ..subpkg2 import mod` 를 실행하면 `pkg.subpkg2.mod` 를 임포트하게 됩니다. 상대 임포트에 대한 규격은 패키지 상대 임포트 절에 들어있습니다.

로드할 모듈들을 동적으로 결정하는 응용 프로그램들을 지원하기 위해 `importlib.import_module()` 이 제공됩니다.

인자 `module`, `filename`, `sys.path`, `sys.meta_path`, `sys.path_hooks`로 감사 이벤트 `import`를 발생시킵니다.

### 7.11.1. Lazy imports

The `lazy` keyword is a soft keyword that only has special meaning when it appears immediately before an `import` or `from` statement. When an import statement is preceded by the `lazy` keyword, the import becomes lazy: the module is not loaded immediately at the import statement. Instead, a lazy proxy object is created and bound to the name. The actual module is loaded on first use of that name.

Lazy imports are only permitted at module scope. Using `lazy` inside a function, class body, or `try`/`except`/`finally` block raises a `SyntaxError`. Star imports cannot be lazy (`lazy from module import *` is a syntax error), and future statements cannot be lazy.

When using `lazy from ... import`, each imported name is bound to a lazy proxy object. The first access to any of these names triggers loading of the entire module and resolves only that specific name to its actual value. Other names remain as lazy proxies until they are accessed.

Example:

    lazy import json
    import sys

    print('json' in sys.modules)  # False - json module not yet loaded

    # First use triggers loading
    result = json.dumps({"hello": "world"})

    print('json' in sys.modules)  # True - now loaded

If an error occurs during module loading (such as `ImportError` or `SyntaxError`), it is raised at the point where the lazy import is first used, not at the import statement itself.

See PEP 810 for the full specification of lazy imports.

Added in version 3.15.

#### 7.11.1.1. Compatibility via `__lazy_modules__`

As an alternative to using the `lazy` keyword, a module can opt into lazy loading for specific imports by defining a module-level `__lazy_modules__` variable. When present, it must be a container of fully qualified module name strings. Any regular (non-`lazy`) `import` statement at module scope whose target appears in `__lazy_modules__` is treated as a lazy import, exactly as if the `lazy` keyword had been used.

This provides a way to enable lazy loading for specific dependencies without changing individual `import` statements. This is useful when supporting Python versions older than 3.15 while using lazy imports in 3.15+:

    __lazy_modules__ = ["json", "pathlib"]

    import json     # loaded lazily (name is in __lazy_modules__)
    import os       # loaded eagerly (name not in __lazy_modules__)

    import pathlib  # loaded lazily

Relative imports are resolved to their absolute name before the lookup, so `__lazy_modules__` must always contain fully qualified module names.

For `from`-style imports, the relevant name is the module following `from`, not the names of its members:

    # In mypackage/mymodule.py
    __lazy_modules__ = ["mypackage", "mypackage.sub.utils"]

    from . import helper         # loaded lazily: . resolves to mypackage
    from .sub.utils import func  # loaded lazily: .sub.utils resolves to mypackage.sub.utils
    import json                  # loaded eagerly (not in __lazy_modules__)

Imports inside functions, class bodies, or `try`/`except`/`finally` blocks are always eager, regardless of `__lazy_modules__`.

Added in version 3.15.

### 7.11.2. 퓨처 문

퓨처 문(future statement)은 컴파일러가 특정한 모듈을 특별한 문법이나 개념을 사용해서 컴파일하도록 만드는 지시어(directive)인데, 그 기능은 미래에 출시되는 파이썬에서 표준이 되는 것입니다.

퓨처 문의 목적은 언어에 호환되지 않는 변경이 도입된 미래 버전의 파이썬으로 옮겨가는 것을 쉽게 만드는 것입니다. 그 기능이 표준이 되는 배포 이전에 모듈 단위로 새 기능을 사용할 수 있도록 만듭니다.

    future_stmt: "from" "__future__" "import" feature ["as" identifier]
                 ("," feature ["as" identifier])*
                 | "from" "__future__" "import" "(" feature ["as" identifier]
                 ("," feature ["as" identifier])* [","] ")"
    feature:     identifier

퓨처 문은 모듈의 거의 처음에 나와야 합니다. 퓨처 문 앞에 나올 수 있는 줄들은:

- 모듈 독스트링(docstring) (있다면),

- 주석

- 빈 줄, 그리고

- 다른 퓨처 문들

퓨처 문을 사용해야 하는 유일한 기능은 `annotations` 입니다 (PEP 563을 참조하십시오).

과거에 퓨처 문을 통해 활성화되던 기능들은 여전히 파이썬 3에 의해 인식됩니다. 이 목록에는 `absolute_import`, `division`, `generators`, `generator_stop`, `unicode_literals`, `print_function`, `nested_scopes` 및 `with_statement` 가 포함됩니다. 이것들은 잉여물인데 항상 활성화되고, 오직 과거 호환성을 위해 유지되고 있기 때문입니다.

퓨처 문은 구체적으로는 컴파일 시점에 인식되고 다뤄집니다: 핵심 구성물들의 의미에 대한 변경은 종종 다른 코드 생성을 통해 구현됩니다. 새 기능이 호환되지 않는 (새로운 예약어처럼) 새로운 문법을 도입하는 경우조차 가능한데, 이 경우는 컴파일러가 모듈을 다르게 파싱할 수 있습니다. 그런 결정들은 실행 시점으로 미뤄질 수 없습니다..

배포마다, 컴파일러는 어떤 기능 이름들이 정의되어 있는지 알고, 만약 퓨처 문이 알지 못하는 기능을 포함하고 있으면 컴파일 시점 에러를 일으킵니다.

직접적인 실행 시점의 개념은 다른 임포트 문들과 같습니다: 표준 모듈 `__future__`, 후에 설명합니다, 다 있고, 퓨처 문이 실행되는 시점에 일반적인 방법으로 임포트됩니다.

흥미로운 실행 시점의 개념들은 퓨처 문에 의해 활성화되는 구체적인 기능들에 달려있습니다.

이런 문장에는 아무것도 특별한 것이 없음에 주의해야 합니다:

    import __future__ [as name]

이것은 퓨처 문이 아닙니다; 아무런 특별한 개념이나 문법적인 제약이 없는 평범한 임포트 문일 뿐입니다.

퓨처 문을 포함하는 모듈 `M` 에 등장하는 내장 함수 `exec()` 와 `compile()` 를 호출해서 컴파일되는 코드는, 기본적으로는, 퓨처 문이 지정하는 새 문법과 개념을 사용합니다. 이것은 `compile()` 에 주는 생략 가능한 인자로 제어될 수 있습니다 — 자세한 내용은 그 함수의 문서를 보십시오.

대화형 인터프리터 프롬프트에서 입력된 퓨처 문은 인터프리터 세션의 남은 기간 효과를 발생시킵니다. 인터프리터가 `-i`, 실행할 스크립트 이름이 전달됩니다, 옵션으로 시작하고, 그 스크립트가 퓨처 문을 포함하면, 스크립트가 실행된 이후에 시작되는 대화형 세션에서도 효과를 유지합니다.

더 보기

PEP 236 - 백 투 더 __future__

  __future__ 메커니즘에 대한 최초의 제안.

## 7.12. `global` 문

    global_stmt: "global" identifier ("," identifier)*

`global` 문은 나열된 식별자들이 전역으로 해석되도록 만듭니다. global 선언 없이 자유 변수들이 전역을 가리킬 수 있기는 하지만, `global` 없이 전역 변수에 값을 대입하는 것은 불가능합니다.

The `global` statement applies to the entire current scope (module, function body or class definition). A `SyntaxError` is raised if a variable is used or assigned to prior to its global declaration in the scope.

At the module level, all variables are global, so a `global` statement has no effect. However, variables must still not be used or assigned to prior to their `global` declaration. This requirement is relaxed in the interactive prompt (REPL).

프로그래머의 주의 사향: `global` 은 파서에 주는 지시자(directive)입니다. `global` 문과 같은 시점에 파싱되는 코드에만 적용됩니다. 특히, 내장 `exec()` 함수로 공급되는 문자열이나 코드 객체에 포함된 `global` 문은 그 함수 호출을 포함하는 코드 블록에는 영향을 주지 않고, 그런 문자열에 포함된 코드 역시 함수 호출을 포함하는 코드에 있는 `global` 문에 영향을 받지 않습니다. `eval()` 과 `compile()` 함수들도 마찬가지입니다.

## 7.13. `nonlocal` 문

    nonlocal_stmt: "nonlocal" identifier ("," identifier)*

When the definition of a function or class is nested (enclosed) within the definitions of other functions, its nonlocal scopes are the local scopes of the enclosing functions. The `nonlocal` statement causes the listed identifiers to refer to names previously bound in nonlocal scopes. It allows encapsulated code to rebind such nonlocal identifiers. If a name is bound in more than one nonlocal scope, the nearest binding is used. If a name is not bound in any nonlocal scope, or if there is no nonlocal scope, a `SyntaxError` is raised.

The `nonlocal` statement applies to the entire scope of a function or class body. A `SyntaxError` is raised if a variable is used or assigned to prior to its nonlocal declaration in the scope.

더 보기

PEP 3104 - 바깥 스코프에 있는 이름들에 대한 액세스

  `nonlocal` 문의 규격.

Programmer’s note: `nonlocal` is a directive to the parser and applies only to code parsed along with it. See the note for the `global` statement.

## 7.14. `type` 문

    type_stmt: 'type' identifier [type_params] "=" expression

The `type` statement declares a type alias, which is an instance of `typing.TypeAliasType`.

For example, the following statement creates a type alias:

    type Point = tuple[float, float]

This code is roughly equivalent to:

    annotation-def VALUE_OF_Point():
        return tuple[float, float]
    Point = typing.TypeAliasType("Point", VALUE_OF_Point())

`annotation-def` indicates an annotation scope, which behaves mostly like a function, but with several small differences.

The value of the type alias is evaluated in the annotation scope. It is not evaluated when the type alias is created, but only when the value is accessed through the type alias’s `__value__` attribute (see Lazy evaluation). This allows the type alias to refer to names that are not yet defined.

Type aliases may be made generic by adding a type parameter list after the name. See Generic type aliases for more.

`type` is a soft keyword.

Added in version 3.12.

더 보기

PEP 695 - Type Parameter Syntax

  Introduced the `type` statement and syntax for generic classes and functions.