`reprlib` — 대안 `repr()` 구현

reprlib — 대안 repr() 구현

reprlib 모듈은 결과 문자열의 크기에 제한을 둔 객체 표현을 만들어 내는 수단을 제공해요. Python 디버거에서 사용되며 다른 문맥에서도 유용할 수 있어요.

이 모듈은 클래스 하나, 인스턴스 하나, 함수 하나를 제공해요.

출처: Python 표준 라이브러리

본문

class reprlib.Repr(*, maxlevel=6, maxtuple=6, maxlist=6, maxarray=5, maxdict=4, maxset=6, maxfrozenset=6, maxdeque=6, maxstring=30, maxlong=40, maxother=30, fillvalue='...', indent=None)

내장 repr()과 비슷한 함수를 구현하는 데 유용한 형식화 서비스를 제공하는 클래스예요. 지나치게 긴 표현이 생성되는 걸 피하기 위해 서로 다른 객체 타입에 대한 크기 제한이 추가돼 있어요.

생성자의 키워드 인자는 Repr 인스턴스의 속성을 설정하는 단축키로 쓸 수 있어요. 즉 다음 초기화는

aRepr = reprlib.Repr(maxlevel=3)

다음과 동등해요.

aRepr = reprlib.Repr()
aRepr.maxlevel = 3

Repr 속성에 대한 자세한 내용은 "Repr Objects" 섹션을 참고하세요. 버전 3.12 변경: 키워드 인자로 속성을 설정할 수 있게 됨.

reprlib.aRepr

아래에 설명한 repr() 함수를 제공하는 데 쓰는 Repr의 인스턴스예요. 이 객체의 속성을 바꾸면 repr()과 Python 디버거가 쓰는 크기 제한이 영향을 받아요.

reprlib.repr(*obj*)

aReprrepr() 메서드예요. 같은 이름의 내장 함수가 반환하는 것과 비슷하지만, 대부분의 크기에 제한이 있는 문자열을 반환해요.

크기 제한 도구에 더해, 이 모듈은 __repr__()에 대한 재귀 호출을 감지하고 그 자리에 플레이스홀더 문자열을 대신 넣는 데코레이터도 제공해요.

@reprlib.recursive_repr(*fillvalue='...'*)

같은 스레드 안에서의 재귀 호출을 감지하는 __repr__() 메서드용 데코레이터예요. 재귀 호출이 발생하면 fillvalue를 반환하고, 아니면 평소처럼 __repr__()을 호출해요. 예를 들어:

>>> from reprlib import recursive_repr
>>> class MyList(list):
...     @recursive_repr()
...     def __repr__(self):
...         return '<' + '|'.join(map(repr, self)) + '>'
...
>>> m = MyList('abc')
>>> m.append(m)
>>> m.append('x')
>>> print(m)
<'a'|'b'|'c'|...|'x'>

버전 3.2에서 추가됨.

Repr 객체 (Repr Objects)

Repr 인스턴스는 서로 다른 객체 타입의 표현에 대한 크기 제한을 제공하는 여러 속성과, 특정 객체 타입을 형식화하는 메서드를 제공해요.

Repr.fillvalue

재귀 참조에 표시되는 문자열이에요. 기본값은 ...예요. 버전 3.11에서 추가됨.

Repr.maxlevel

재귀 표현 생성의 깊이 제한이에요. 기본값은 6이에요.

Repr.maxdict, Repr.maxlist, Repr.maxtuple, Repr.maxset, Repr.maxfrozenset, Repr.maxdeque, Repr.maxarray

명명된 객체 타입에 대해 표시되는 항목 수의 제한이에요. 기본값은 maxdict4, maxarray5, 나머지는 6이에요.

Repr.maxlong

정수 표현에서의 최대 문자 수예요. 가운데에서 자릿수가 잘려나가요. 기본값은 40이에요.

Repr.maxstring

문자열 표현에서의 최대 문자 수 제한이에요. "정상적인" 문자열 표현이 문자 소스로 쓰인다는 점에 주의하세요. 표현에 이스케이프 시퀀스가 필요하다면, 표현이 짧아질 때 그것들이 망가질 수 있어요. 기본값은 30이에요.

Repr.maxother

Repr 객체에 특정 형식화 메서드가 없는 객체 타입의 크기를 제어하는 데 쓰는 제한이에요. maxstring과 비슷한 방식으로 적용돼요. 기본값은 20이에요.

Repr.indent

이 속성이 None(기본값)이면 표준 repr()처럼 줄 바꿈이나 들여쓰기 없이 출력이 형식화돼요. 예를 들어:

>>> example = [
...     1, 'spam', {'a': 2, 'b': 'spam eggs', 'c': {3: 4.5, 6: []}}, 'ham']
>>> import reprlib
>>> aRepr = reprlib.Repr()
>>> print(aRepr.repr(example))
[1, 'spam', {'a': 2, 'b': 'spam eggs', 'c': {3: 4.5, 6: []}}, 'ham']

indent를 문자열로 설정하면 각 재귀 수준이 그 문자열로 들여쓰기된 채 자기 줄에 놓여요:

>>> aRepr.indent = '-->'
>>> print(aRepr.repr(example))
[
-->1,
-->'spam',
-->{
-->-->'a': 2,
-->-->'b': 'spam eggs',
-->-->'c': {
-->-->-->3: 4.5,
-->-->-->6: [],
-->-->},
-->},
-->'ham',
]

indent를 양의 정수 값으로 설정하면 그 수만큼의 공백을 가진 문자열로 설정된 것처럼 동작해요:

>>> aRepr.indent = 4
>>> print(aRepr.repr(example))
[
    1,
    'spam',
    {
        'a': 2,
        'b': 'spam eggs',
        'c': {
            3: 4.5,
            6: [],
        },
    },
    'ham',
]

버전 3.12에서 추가됨.

Repr.repr(*obj*)

인스턴스가 부과한 형식화를 사용하는 내장 repr()에 해당하는 메서드예요.

Repr.repr1(*obj*, *level*)

repr()이 사용하는 재귀 구현이에요. obj의 타입을 사용해 어떤 형식화 메서드를 호출할지 정하고, objlevel을 그 메서드에 넘겨요. 타입별 메서드는 재귀 호출에서 level - 1 값을 level로 하여 repr1()을 호출해 재귀 형식화를 수행해야 해요.

Repr.repr_TYPE(*obj*, *level*)

특정 타입에 대한 형식화 메서드는 타입 이름에 기반한 이름을 가진 메서드로 구현돼요. 메서드 이름에서 TYPE'_'.join(type(obj).__name__.split())으로 바뀌어요. 이 메서드들로의 디스패치는 repr1()이 처리해요. 값을 재귀적으로 형식화해야 하는 타입별 메서드는 self.repr1(subobj, level - 1)을 호출해야 해요.

Repr 객체 서브클래싱 (Subclassing Repr Objects)

Repr.repr1()의 동적 디스패치 사용 덕분에 Repr의 하위 클래스가 추가적인 내장 객체 타입에 대한 지원을 더하거나 이미 지원되는 타입의 처리를 수정할 수 있어요. 다음 예시는 파일 객체에 대한 특별 지원을 추가하는 방법을 보여줘요:

import reprlib
import sys

class MyRepr(reprlib.Repr):

    def repr_TextIOWrapper(self, obj, level):
        if obj.name in {'<stdin>', '<stdout>', '<stderr>'}:
            return obj.name
        return repr(obj)

aRepr = MyRepr()
print(aRepr.repr(sys.stdin))         # prints '<stdin>'
<stdin>