[Final] PEP 3113 - Removal of Tuple Parameter Unpacking

원문 링크: PEP 3113 - Removal of Tuple Parameter Unpacking

상태: Final 유형: Standards Track 작성일: 02-Mar-2007

PEP 3113 – 튜플 매개변수 언패킹 제거

개요

이 문서는 Python 3.0에서 튜플 매개변수 언패킹(Tuple Parameter Unpacking) 기능을 제거할 것을 제안합니다. 튜플 매개변수 언패킹은 함수 시그니처(function signature)에서 튜플을 매개변수로 사용하여 시퀀스(sequence) 인자가 자동으로 언패킹되도록 하는 기능입니다.

예시:

def fxn(a, (b, c), d):
    pass

위 예시에서 (b, c)를 시그니처에 사용하는 것은 함수의 두 번째 인자가 길이가 2인 시퀀스(예: [42, -13])여야 함을 의미합니다. 이러한 시퀀스가 전달되면 마치 b, c = [42, -13] 문이 매개변수 내부에서 실행된 것처럼 값이 언패킹되어 각 매개변수에 할당됩니다.

이 기능은 특정 상황에서 편리할 수 있지만, 발생하는 문제점이 이점보다 크다고 판단되어 Python 3.0에서 제거될 것을 제안합니다.

제거되어야 하는 이유

인트로스펙션(Introspection) 문제

Python은 강력한 인트로스펙션 기능을 제공하며, 이는 함수 시그니처에도 적용됩니다. 그러나 튜플 매개변수에서는 인트로스펙션에 상당한 어려움이 있습니다.

  • 내부적인 이름 처리: 튜플 매개변수는 함수의 코드 객체(code object)에 있는 co_varnames 속성에서 .1과 같은 숫자와 점(.)으로 구성된 이름으로 표시됩니다. 이는 바이트코드(bytecode)만이 인식하는 이름에 튜플 인자를 바인딩(bind)합니다.
  • 형식 정보 부족: 이 방식은 튜플의 길이, 중첩 튜플 여부 등 튜플의 자세한 형식을 지정하지 않습니다.
  • 바이트코드 분석 필수: 튜플의 모든 세부 정보를 얻으려면 함수의 바이트코드를 분석해야 합니다. 이는 inspect.getargspec 함수가 튜플 매개변수에 대한 정보를 제공하는 방식이기도 합니다.
  • 구현 부담: 바이트코드 분석은 쉽지 않으며, 다른 유형의 매개변수는 바이트코드 지식을 요구하지 않는 반면, 튜플 매개변수는 인트로스펙션 도구에 불필요한 부담을 줍니다.
  • 타 구현체(Other Implementations)와의 호환성 문제: IronPython과 같이 Python의 바이트코드를 사용하지 않고 .NET 프레임워크 기반으로 MSIL을 func_code.co_code 속성에 저장하는 구현체에서는 inspect.getargspec 함수가 작동하지 않습니다.

기능 손실 없음

튜플 매개변수를 처리하기 위해 함수의 바이트코드는 인자를 적절한 매개변수 이름으로 언패킹하는 데 필요한 바이트코드로 시작합니다. 이는 튜플 매개변수를 구현하기 위해 특별한 지원이 필요하지 않다는 것을 의미하며, 따라서 이 기능을 제거해도 어떠한 기능적 손실도 발생하지 않습니다. 단지 편의성 측면에서의 손실만 있을 뿐입니다.

예시:

def fxn(a, (b, c), d):
    pass

위 함수는 다음과 같이 쉽게 재작성할 수 있으며, 기능적으로 아무런 손실이 없습니다.

def fxn(a, b_c, d):
    b, c = b_c
    pass

규칙의 예외 (Exception To The Rule)

Python 함수의 다양한 매개변수 유형을 살펴보면, 튜플 매개변수는 규칙이라기보다는 예외적인 경향이 있습니다.

  • PEP 3102 (키워드 전용 인자) 및 PEP 3107 (함수 어노테이션): 두 PEP 모두 함수의 시그니처 내에 새로운 기능을 도입했지만, 이 새로운 기능은 튜플 매개변수 전체에 적용될 수 없습니다.
    • PEP 3102는 튜플 매개변수를 전혀 지원하지 않습니다 (이름으로 튜플 매개변수를 참조할 방법이 없으므로 당연합니다).
    • PEP 3107은 튜플 내 각 항목에 대한 어노테이션(예: (x:int, y:int))은 허용하지만, 튜플 전체에 대한 어노테이션(예: (x, y):int)은 허용하지 않습니다.
  • 시퀀스와 매핑 객체 간의 불균형: 튜플 매개변수의 존재는 함수 시그니처에서 시퀀스 객체를 매핑 객체(예: dict)와 분리된 위치에 두게 합니다. 매핑 객체를 매개변수로 전달하여 시퀀스가 튜플 매개변수로 언패킹되는 방식과 동일하게 언패킹할 방법이 없습니다.

비정보적인 오류 메시지 (Uninformative Error Messages)

튜플 매개변수를 사용할 때 발생하는 오류 메시지는 명확하지 않을 수 있습니다.

예시:

def fxn((a, b), (c, d)):
    pass

fxn(1, (2, 3))

위 코드를 실행하면 TypeError: unpack non-sequence 오류 메시지가 발생합니다. 이 메시지는 어떤 튜플이 제대로 언패킹되지 않았는지 전혀 알려주지 않으며, 이것이 인자(arguments)로 인해 발생한 결과라는 표시도 없습니다. 다른 인자 관련 오류 메시지(예: TypeError: fxn() takes exactly 2 arguments (0 given))는 시그니처와의 관계를 명시적으로 언급하는 것과 대조적입니다.

낮은 사용률 (Little Usage)

비공식적인 설문조사 결과, 대부분의 Python 개발자가 이 기능을 알지 못하거나 사용하지 않는 것으로 나타났습니다. Python 코드 저장소의 Lib/ 디렉토리에서 함수 및 메서드 정의를 검사한 결과, def 문 중 약 0.18%만이 튜플 매개변수를 사용하는 것으로 나타났습니다. 이는 이 기능이 널리 사용되지 않음을 뒷받침합니다.

유지되어야 한다는 주장 (제거되어서는 안 되는 이유)

실용적인 사용 (Practical Use)

어떤 경우에는 튜플 매개변수가 유용할 수 있습니다. 예를 들어, 데카르트 좌표계를 나타내는 두 항목 튜플을 인자로 받는 코드에서 xy 좌표를 자동으로 언패킹하는 것이 편리하다는 주장이 있습니다. 그러나 이러한 실용적인 이점은 튜플 매개변수와 관련된 다른 문제점들에 비해 훨씬 적다고 판단됩니다. 또한, 기능 손실이 없다는 점(No Loss Of Abilities If Removed)에서 보았듯이, 이 기능은 순전히 실용적인 편의를 제공할 뿐이며 다른 방법으로 쉽게 처리할 수 없는 고유한 능력을 제공하지 않습니다.

매개변수의 자기 문서화 (Self-Documentation For Parameters)

튜플 매개변수가 특정 시퀀스 형식으로 예상되는 매개변수에 대한 자기 문서화(self-documentation) 방법을 제공한다는 주장이 있습니다. 위의 데카르트 좌표 예시에서 (x, y)를 매개변수로 보는 것은 길이가 2인 튜플이 인자로 예상된다는 것을 명확하게 알려줍니다.

그러나 Python은 매개변수의 용도를 문서화하는 다른 여러 방법을 제공합니다.

  • 문서화 문자열 (Docstrings): 문서화 문자열은 예상되는 인자에 대한 충분한 정보를 제공하기 위해 존재합니다. 튜플 매개변수는 시퀀스 인자의 예상 길이를 알려줄 수 있지만, 데이터가 무엇에 사용될지는 알려주지 않습니다. 모든 매개변수가 튜플 매개변수가 아니라면 다른 인자에 대한 정보를 알기 위해 Docstring을 읽어야 합니다.
  • 함수 어노테이션 (Function Annotations): (튜플 매개변수와는 작동하지 않지만) 함수 어노테이션도 문서화를 제공할 수 있습니다. 어노테이션은 어떤 형태도 될 수 있으므로, 이전의 튜플 매개변수는 tuple, tuple(2), Cartesian point, (x, y) 등과 같은 어노테이션을 가진 단일 인자 매개변수가 될 수 있습니다. 어노테이션은 특정 길이의 시퀀스를 포함하여 매개변수에 대한 인자가 무엇인지 문서화하는 데 큰 유연성을 제공합니다.

전환 계획 (Transition Plan)

튜플 매개변수가 제거되는 Python 3.x로 Python 2.x 코드를 전환하기 위해 두 가지 단계가 제안됩니다.

  1. 경고 발생: Python 2.6에서 Python 컴파일러가 튜플 매개변수를 발견하면 적절한 경고(warning)를 발생시킵니다. 이는 Python 2.6과 Python 3.0 사이에 발생하는 다른 모든 문법적 변경 사항과 동일하게 처리됩니다.
  2. 2to3 리팩토링 도구 지원: 2to3 리팩토링 도구는 튜플 매개변수를 함수 내 첫 번째 문에서 언패킹되는 단일 매개변수로 변환하는 fixer를 추가할 예정입니다. 새 매개변수의 이름이 변경되고, 이 새 매개변수는 원래 튜플 매개변수에서 사용된 이름으로 언패킹됩니다.

    예시:

    def fxn((a, (b, c))):
        pass
    

    다음과 같이 번역됩니다.

    def fxn(a_b_c):
        (a, (b, c)) = a_b_c
        pass
    

    람다(lambda)에서는 단일 표현식(single expression) 제한 때문에 튜플 매개변수가 사용되므로, 람다 또한 지원되어야 합니다. 이는 예상되는 시퀀스 인자를 단일 매개변수에 바인딩한 다음 해당 매개변수에 인덱싱(indexing)하는 방식으로 처리됩니다.

    예시:

    lambda (x, y): x + y
    

    다음과 같이 번역됩니다.

    lambda x_y: x_y[0] + x_y[1]
    

참고 자료 (References)

  • 2to3 리팩토링 도구
  • 2to3 fixer
  • IronPython
  • Microsoft Intermediate Language

이 문서는 퍼블릭 도메인(public domain)에 공개되었습니다.

⚠️ 알림: 이 문서는 AI를 활용하여 번역되었으며, 기술적 정확성을 보장하지 않습니다. 정확한 내용은 반드시 원문을 확인하시기 바랍니다.

Comments