[Rejected] PEP 3140 - str(container) should call str(item), not repr(item)

원문 링크: PEP 3140 - str(container) should call str(item), not repr(item)

상태: Rejected 유형: Standards Track 작성일: 27-May-2008

PEP 3140 – str(container)repr(item) 대신 str(item)을 호출해야 합니다.

  • 작성자: Oleg Broytman, Jim J. Jewett
  • 상태: Rejected (거절됨)
  • 유형: Standards Track
  • 생성일: 2008년 5월 27일

거절 사유

Guido van Rossum은 이 제안이 베타 버전 출시가 임박한 시점에 너무 많은 혼란을 야기할 것이라고 판단하여 거절했습니다.

개요 (Abstract)

이 문서는 현재 str(container) 구현 방식의 장단점을 논의합니다. 또한, repr(item) 대신 str(item)을 호출하는 다른 접근 방식의 장단점도 함께 다룹니다.

동기 (Motivation)

현재 str(container)는 컨테이너 내의 각 항목에 대해 repr()를 호출합니다.

찬성 논거:

  • 컨테이너는 str(container) 호출 시 사용자가 어떤 내용을 보기를 원하는지 (예: 주위 문자, 구분 기호 등) 추측하지 않으려 합니다.
  • repr(item)은 일반적으로 타입 정보(예: 문자열 주변의 아포스트로피, 클래스 이름 등)를 표시합니다.

반대 논거:

  • 이는 논리적이지 않습니다. str()은 존재한다면 __str__을 호출할 것으로 예상되며, __repr__을 호출할 것으로 예상되지 않습니다.
  • 항목의 __str__을 호출하여 컨테이너 내용을 출력하는 표준적인 방법이 없으며, __str____repr__이 다른 결과를 반환하는 경우에 불편합니다.
  • repr(item)은 때때로 잘못된 동작을 합니다 (예: 비-ASCII 문자열을 16진수로 이스케이프 처리).

이 PEP는 str(container)의 작동 방식을 변경할 것을 제안합니다. repr(container)의 작동 방식을 모방하되, 항목에 대해 repr 대신 str을 호출하는 한 가지 세부 사항만 다르게 할 것을 제안합니다. 이는 사용자가 item.__repr__ 또는 item.__str__ 중 어떤 결과를 얻을지 선택할 수 있도록 합니다.

현재 상황 (Current situation)

대부분의 컨테이너 타입(튜플, 리스트, 딕셔너리, 세트 등)은 __str__ 메서드를 구현하지 않습니다. 따라서 str(container)container.__repr__을 호출하고, container.__repr__str로부터 호출되었는지 여부를 잊고 항상 컨테이너 항목에 대해 repr을 호출합니다.

이러한 동작에는 장단점이 있습니다. 한 가지 장점은 대부분의 항목이 타입 정보와 함께 표현된다는 것입니다. 예를 들어, 문자열은 아포스트로피로 둘러싸이고, 인스턴스는 클래스 이름과 인스턴스 데이터를 모두 가질 수 있습니다.

>>> print([42, '42'])
[42, '42']
>>> print([Decimal('42'), datetime.now()])
[Decimal("42"), datetime.datetime(2008, 5, 27, 19, 57, 43, 485028)]

단점은 __repr__이 종종 기술적인 데이터(예: <object at address>) 또는 읽기 어려운 문자열(예: 비-ASCII 문자열의 경우 16진수로 인코딩된 문자열)을 반환한다는 것입니다.

>>> print(['тест'])
['\xd4\xc5\xd3\xd4']

PEP 3138의 동기 중 하나는 reprstr 모두 키가 비-ASCII 텍스트 문자열인 딕셔너리를 합리적으로 출력할 수 없다는 것입니다. 유니코드 식별자가 허용되면서, 이는 Python 자체의 속성 딕셔너리에도 해당됩니다. 또한 JSON 직렬화에도 영향을 미쳤습니다.

str(container)의 작동 방식을 변경하면 일반적인 경우에 쉬운 디버깅이 가능하고, 기계가 읽을 수 있는 경우에는 ASCII-only의 안전성을 유지할 수 있습니다. 유일한 단점은 str(x)repr(x)가 더 자주 달라질 수 있다는 것이지만, 이는 현재 거의 동일한 버전으로 불충분한 경우에만 해당됩니다.

또한 str(container)가 항목에 대해 str 대신 repr을 호출하는 것은 비논리적으로 보입니다. 다음 코드가 아래와 같이 출력될 것으로 예상하는 것이 논리적입니다.

class Test:
    def __str__(self):
        return "STR"
    def __repr__(self):
        return "REPR"
test = Test()
print(test)
print(repr(test))
print([test])
print(str([test]))

예상되는 출력:

STR
REPR
[STR]
[STR]

하지만 실제 출력은 다음과 같습니다:

STR
REPR
[REPR]
[REPR]

특히 Python 2에서 print가 튜플로 보이는 것에 대해 호출될 때 str을 사용하는 것은 비논리적입니다.

>>> print Decimal('42'), datetime.now()
42 2008-05-27 20:16:22.534285

실제 튜플에 대해서는 다음과 같이 출력됩니다.

>>> print((Decimal('42'), datetime.now()))
(Decimal("42"), datetime.datetime(2008, 5, 27, 20, 16, 27, 937911))

다른 접근 방식: str(item) 호출 (A different approach - call str(item))

예를 들어, 숫자에서는 종종 값 자체에만 관심이 있습니다.

>>> print Decimal('3')
3

그러나 이 값을 리스트에 넣으면, 마치 기계를 위해 repr이 호출된 것처럼 사용자는 타입 정보를 읽어야 합니다.

>>> print [Decimal('3')]
[Decimal("3")]

이 변경 후에는 타입 정보가 str 출력에 혼란을 주지 않을 것입니다.

>>> print "%s".format([Decimal('3')])
[3]
>>> str([Decimal('3')]) # == [3]

하지만 필요하다면 여전히 타입 정보를 얻을 수 있습니다.

>>> print "%r".format([Decimal('3')])
[Decimal('3')]
>>> repr([Decimal('3')]) # == [Decimal('3')]

이 문제를 해결하기 위한 여러 전략이 있습니다. 가장 급진적인 방법은 __repr__이 새로운 매개변수(플래그) “str에서 호출되었으므로 항목에 대해 repr이 아닌 str을 호출하라”를 받아들이도록 변경하는 것입니다. 이 제안의 단점은 모든 __repr__ 구현이 변경되어야 한다는 것입니다. 인트로스펙션(introspection)이 약간 도움이 될 수 있지만(호출하기 전에 __repr__이 2개 또는 3개의 매개변수를 받아들이는지 검사), 내장 컨테이너와 같이 C로 작성된 클래스에서는 인트로스펙션이 작동하지 않습니다.

덜 급진적인 제안은 내장 컨테이너 타입에 대해 __str__ 메서드를 구현하는 것입니다. 명백한 단점은 노력의 중복입니다. 이 모든 __str____repr__ 구현은 항목에 대해 str을 호출할지 repr을 호출할지 여부라는 작은 세부 사항에서만 다릅니다.

가장 보수적인 제안은 str을 전혀 변경하지 않고 개발자가 자체 애플리케이션 또는 라이브러리별 “pretty-printers”를 구현하도록 허용하는 것입니다. 이 역시 노력의 증대와 많은 작고 구체적인 컨테이너 순회 알고리즘의 확산이라는 단점이 있습니다.

하위 호환성 (Backward compatibility)

타입 정보가 평소보다 더 중요한 경우, 명시적으로 repr을 호출하여 현재와 동일한 결과를 얻는 것이 여전히 가능할 것입니다.

참고 자료 (References)

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

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

Comments