Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python 개선 제안 한국어 번역

PEP 679 – 괄호를 사용하는 새로운 assert 문 구문

Author:
Pablo Galindo Salgado <pablogsal at python.org>, Stan Ulbrych <stan at python.org>
Discussions-To:
Discourse thread
Status:
Rejected
Type:
Standards Track
Created:
07-Jan-2022
Python-Version:
3.15
Post-History:
08-Sep-2025, 10-Jan-2022
Resolution:
24-Oct-2025

Table of Contents

번역·라이선스 안내

이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain or CC0-1.0, whichever is more permissive 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판

초록

이 PEP에서는 assert의 두 인자 형식에서 괄호를 사용할 수 있도록 제안합니다. 인터프리터는 assert (expr, msg)assert expr, msg로 재해석하여, 이러한 코드가 항상 참인 두 요소짜리 tuple을 단언하는 것으로 처리되던 일반적인 함정을 제거합니다.

동기

오류 메시지를 포함하는 assert 문 형식을 사용할 때 메시지를 괄호로 감싸는 것은 흔한 사용자 실수입니다 [1] [2]. 이는 많은 초보자가 assert를 함수라고 생각하기 때문입니다. 널리 사용되는 unittest 메서드, 특히 assertTrue()도 단언식과 메시지 주위에 괄호를 사용해야 합니다.

안타깝게도 이 실수는 assert가 항상 성공하므로 [6], 발견되지 않은 채 넘어갑니다. 이는 해당 식이 항상 참인 값을 갖는 두 요소 튜플인 assert 문으로 해석되기 때문입니다. 괄호는 여러 줄로 작성하는 자연스러운 방법이므로, 테스트나 설명을 한 줄보다 길게 확장할 때도 이 실수가 자주 발생합니다.

이 실수가 매우 흔하기 때문에 3.10부터 컴파일러와 여러 코드 린터에서 [3] [4] SyntaxWarningemitted by the compiler 됩니다.

또한 언어의 일부 다른 문도 어떤 방식으로든 괄호를 사용한 형식을 허용합니다. 예를 들어 import 문(from x import (a,b,c))이나 del 문(del (a,b,c))이 있습니다.

괄호를 허용하면 이러한 함정을 제거할 뿐만 아니라, 사용자가 긴 assert 문을 여러 줄에 걸쳐 형식화할 수 있고 자동 포매터도 그렇게 할 수 있으므로, 이 문서의 저자들이 더 자연스럽다고 생각하는 방식으로 작성할 수 있습니다. 현재도 백슬래시(PEP 8에서 권장하는 방식) 또는 괄호와 쉼표를 사용하여 긴 assert 문을 여러 줄에 걸쳐 형식화할 수 있지만:

assert (
  very very long
  test
), (
  "very very long "
  "error message"
)

이 문서의 저자들은 제안된 괄호 사용 형식이 더 명확하고 직관적이며, 다른 문법 구성 요소의 형식과도 더 일관된다고 생각합니다.:

assert (
  very very long
  test,

  "very very long "
  "message"
)

근거

하위 호환성 문제(아래 절 참조)로 인해, 이전에 두 요소 튜플이었던 항목이 새롭게 구문 분석되는 방식을 사용자에게 알리기 위해 "new assertion syntax, will assert first element of tuple"와 같은 메시지의 SyntaxWarning이 Python 3.17까지 발생합니다. 예를 들어 새 구문을 사용할 때는 다음과 같습니다.

>>> assert ('Petr' == 'Pablo', "That doesn't look right!")
<python-input-0>:0: SyntaxWarning: new assertion syntax, will assert first element of tuple
Traceback (most recent call last):
  File "<python-input-0>", line 1, in <module>
    assert ('Petr' == 'Pablo', "That doesn't look right!")
            ^^^^^^^^^^^^^^^^^
AssertionError: That doesn't look right!

일반적으로 구문 경고를 개선하는 것은 이 PEP의 범위를 벗어난다는 점에 유의하십시오.

사양

assert 문에 대한 정식 문법은 다음과 같이 변경됩니다 [8]:

| 'assert' '(' expression ',' expression [','] ')' &(NEWLINE | ';')
| 'assert' a=expression [',' expression ]

첫 번째 줄은 괄호를 허용하며 3.17까지 SyntaxWarning을 발생시키는 새로운 assert 문 형식입니다. 룩어헤드는 파서가 튜플을 전체 문으로 성급하게 캡처하는 것을 방지하기 위해 필요하므로, assert (a, b) <= c, "something"과 같은 문도 올바르게 구문 분석됩니다.

구현 참고 사항

이 변경 사항은 파서 또는 컴파일러에서 구현할 수 있습니다. 새 구문을 사용자에게 알리는 SyntaxWarning을 발생시켜야 한다는 사양은 경고가 컴파일 중에 발생해야 하므로 구현을 복잡하게 만듭니다.

저자들은 이상적인 구현이 파서에서 이루어져 [8], assert (x,y)assert x,y와 동일한 AST를 갖게 될 것이라고 생각합니다. 이를 위해서는 필요한 임시 절충안을 포함한 2단계 구현 계획이 필요합니다.

파서에서 구현하기

경고 사양이 있는 순수한 파서 구현은 불가능합니다. (경고 사양이 없다면 순수한 파서 구현은 작은 문법 변경에 불과하다는 점에 유의하십시오 [5]). 경고를 발생시키려면 컴파일러가 새 구문을 인식해야 하므로, 그렇지 않으면 구문 분석 중에 정보가 손실되기 때문에 선택적 플래그가 필요합니다. 따라서 괄호가 있는 assert의 AST는 paren_syntax=1 플래그를 사용하여 다음과 같이 표시됩니다.:

>>> print(ast.dump(ast.parse('assert(True, "Error message")'), indent=4))
Module(
    body=[
        Assert(
            test=Constant(value=True),
            msg=Constant(value='Error message'),
            paren_syntax=1)])

컴파일러에서 구현하기

새로운 구문은 길이가 2인 튜플을 특별히 처리하여 컴파일러에서 구현할 수 있습니다. 그러나 이렇게 하면 SyntaxWarning이 발생하는 전환 기간 동안 AST를 전혀 수정하지 않는 부작용이 생깁니다.

관련 SyntaxWarning이 제거되면 구현을 파서 수준으로 옮길 수 있으며, 여기서 괄호로 묶인 형식은 assert expression, message와 동일한 AST 구조로 직접 구문 분석됩니다. AST를 처리하는 많은 도구가 적응할 시간이 더 주어지므로 이 접근 방식이 하위 호환성이 더 높습니다.

하위 호환성

이 변경은 기술적으로 하위 호환되지 않습니다. 파서에서 먼저 구현하든 컴파일러에서 먼저 구현하든, 현재는 2-튜플을 피연산자로 하는 assert 문으로 해석되어 항상 참으로 평가되는 assert (x,y)assert x,y로 해석됩니다.

반면 이러한 종류의 assert 문은 항상 성공하므로 사용자 코드에서 사실상 아무 작업도 수행하지 않습니다. 이 문서의 작성자들은 이러한 하위 호환성 중단의 성격이 유익하다고 생각합니다. 이전에는 눈에 띄지 않은 채 통과했을 이러한 사례가 사용자 코드에서 드러나기 때문입니다. 이 사례는 Python 3.10부터 이미 SyntaxWarning을 발생시켜 왔으므로, 5년이 넘는 지원 중단 기간이 있었습니다. 이러한 놀라움은 SyntaxWarning이 계속 발생함으로써 완화되어야 합니다.

또한 이 변경으로 assert (x,y)의 AST가 변경되며, 현재는 다음과 같습니다:

Module(
    body=[
        Assert(
            test=Tuple(
                elts=[
                    Name(id='x', ctx=Load()),
                    Name(id='y', ctx=Load())],
                ctx=Load()))],
    type_ignores=[])

Python 3.18의 최종 구현에서는 다음 AST가 생성됩니다:

Module(
    body=[
        Assert(
            test=Name(id='x', ctx=Load()),
            msg=Name(id='y', ctx=Load()))],
    type_ignores=[])

이때의 문제는 첫 번째 형식의 AST가 기술적으로 “incorrect”가 된다는 것입니다. 테스트와 메시지가 있는 assert 문의 AST에는 이미 특수화된 형식이 존재하기 때문입니다(두 번째 형식). 컴파일러에서 먼저 구현하면 이 변경이 지연되므로 하위 호환성에 대한 우려가 완화되며, 도구가 조정할 시간이 더 주어집니다.

이것을 가르치는 방법

새로운 assert문 형식은 언어 표준의 일부로 문서화됩니다.

사용자에게 오류 메시지가 있는 assert문 형식을 가르칠 때, 이제 괄호를 추가해도 예상대로 작동하며 여러 줄에 걸쳐 문을 나눌 수 있다고 설명할 수 있습니다.

참조 구현

파서의 참조 구현은 이 branch에서 확인할 수 있으며, 컴파일러의 참조 구현은 이 branch에서 확인할 수 있습니다.

거부된 아이디어

키워드를 사용하는 구문 추가

Python 구문의 다른 모든 곳에서는 쉼표가 tuple이나 list의 항목, 함수의 매개변수/인자 또는 import 대상과 같은 동종 요소로 이루어진 가변 길이 “목록”을 구분합니다. Python 3.0에서 except...as를 도입한 후에도 assert문은 이 관례의 유일한 예외로 남아 있습니다.

쉼표로 구분된 항목이 서로 동등하다는 기대에서, 적어도 부분적으로는 사용자 혼란이 비롯되었을 가능성이 있습니다. 괄호로 assert문의 식과 메시지를 묶으면 시각적으로 둘을 더욱 긴밀하게 결합하게 됩니다. assert를 함수 호출과 더 비슷하게 보이도록 만들면 잘못된 사고방식을 조장합니다.

가능한 해결책으로 쉼표를 키워드로 대체하자는 제안이 [7]되었으며, 이 형식에서는 예를 들어 괄호를 사용할 수 있습니다.:

assert condition else "message"
assert (condition else "message")

그런 다음 괄호 안에 나타나는 경우부터 시작하여 쉼표 사용을 서서히 신중하게 지원 중단할 수 있으며, 이 경우에는 이미 SyntaxWarning이 발생합니다.

이 PEP의 작성자들은 완전히 새로운 구문을 추가해도 무엇보다 먼저 이 PEP가 해결하려는 초보자의 흔한 함정을 해결하지 못하며, 여러 줄에 걸친 assert 문의 서식도 개선하지 못한다고 생각합니다. 반면 제안된 구문은 이를 개선한다고 작성자들은 생각합니다.

보안 관련 사항

이 변경 사항에는 보안 관련 영향이 없습니다.

감사의 말

이 변경 사항은 python/cpython#90325에서 처음 논의되고 제안되었습니다.

이 PEP의 초안 작성 과정에서 도움을 주신 Petr Viktorin에게 깊이 감사드립니다.

각주