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

Python 개선 제안 한국어 번역

PEP 3140 – str(container)은 str(item)을 호출해야 하며, repr(item)을 호출해서는 안 됩니다.

Author:
Oleg Broytman <phd at phdru.name>, Jim J. Jewett <jimjjewett at gmail.com>
Discussions-To:
Python-3000 list
Status:
Rejected
Type:
Standards Track
Created:
27-May-2008
Post-History:
28-May-2008

Table of Contents

번역·라이선스 안내

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

거부

Guido는 베타 버전에 너무 가까운 시점에 이렇게 변경하면 혼란이 너무 클 것이라고 말했습니다. [1]를 참조하십시오.

초록

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

동기

현재 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__에서 어떤 결과를 얻을지 선택할 수 있습니다.

현재 상황

대부분의 컨테이너 타입(튜플, 리스트, 딕셔너리, 집합 등)은 __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이 키가 ASCII가 아닌 텍스트 문자열인 딕셔너리를 reprstr도 합리적으로 출력할 수 없다는 것입니다. 이제 유니코드 식별자가 허용되므로 여기에는 Python 자체의 속성 딕셔너리도 포함됩니다. 여기에는 JSON 직렬화도 포함되며, json 라이브러리에 여러 우회 방법을 사용하게 만든 원인이기도 합니다.

PEP 3138에서는 “repr은 안전한 ASCII”라는 불변 조건을 깨고, 일부 객체를 출력하는 repr(영속성에 사용됨)의 방식을 변경하여 시스템에 따라 실패하도록 함으로써 이 문제를 해결할 것을 제안합니다.

str(container)의 작동 방식을 변경하면 일반적인 경우에 손쉬운 디버깅이 가능해지고, 기계가 읽을 수 있는 경우에는 ASCII 전용의 안전성도 유지할 수 있습니다. 유일한 단점은 현재 거의 동일한 버전으로는 부족한 경우에만 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)를 호출하기

예를 들어 숫자의 경우 사람들은 대개 값에만 관심이 있습니다.

>>> 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__ 구현을 변경해야 한다는 점입니다. 인트로스펙션을 사용하면 어느 정도 도움이 될 수 있습니다(__repr__을 호출하기 전에 매개변수를 2개 또는 3개 받는지 검사할 수 있습니다). 그러나 모든 내장 컨테이너처럼 C로 작성된 클래스에서는 인트로스펙션이 작동하지 않습니다.

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

가장 보수적인 제안은 str을 전혀 변경하지 않고 개발자가 애플리케이션별 또는 라이브러리별 자체 pretty-printer를 구현할 수 있도록 허용하는 것입니다. 단점은 다시 작업량이 늘어나고 컨테이너를 순회하는 작고 구체적인 알고리즘이 많이 생긴다는 점입니다.

하위 호환성

타입 정보가 평소보다 더 중요한 경우에는 repr을 명시적으로 호출하여 현재 결과를 얻을 수 있습니다.

참고 자료