클래스 객체에 대한 사용자 정의 문자열 표현을 만드는 방법은 무엇입니까?


202

이 수업을 고려하십시오.

class foo(object):
    pass

기본 문자열 표현은 다음과 같습니다.

>>> str(foo)
"<class '__main__.foo'>"

이 디스플레이를 사용자 정의 문자열로 만들려면 어떻게해야합니까?

답변:


272

구현 __str__()하거나 __repr__()클래스의 메타 클래스입니다.

class MC(type):
  def __repr__(self):
    return 'Wahaha!'

class C(object):
  __metaclass__ = MC

print C

사용은 __str__당신이 읽을 수있는 문자열 화 (stringification) 사용을 의미하는 경우 __repr__명확한 표현에 대한합니다.


2
일종의 클래스 데코레이터를 만들고 싶습니다. 따라서 클래스마다 메타 클래스를 작성하지 않고도 클래스에 대한 사용자 정의 문자열 표현을 쉽게 설정할 수 있습니다. 나는 파이썬의 메타 클래스에 익숙하지 않으므로 거기에 포인터를 줄 수 있습니까?
Björn Pollex

불행히도 이것은 클래스 데코레이터로는 불가능합니다. 클래스가 정의 될 때 설정되어야합니다.
이그나시오 바스케스-아 브람스

10
@ Space_C0wb0y : _representation클래스 본문과 메타 클래스 return self._representation__repr__()메소드 와 같은 문자열을 추가 할 수 있습니다 .
Sven Marnach

@ BjörnPollex 당신은 이것을 데코레이터로 끌어낼 수 있을지 모르지만, 당신은 언어의 많은 미묘함과 싸워야 할 것으로 기대합니다. 그리고 당신이하더라도 메타 클래스를 어떤 식 으로든 사용할 수밖에 없습니다. 왜냐하면 기본값 __repr__을 사용하여을 나타내 기를 원하지 않기 때문 C입니다. _representation멤버 를 갖는 대안 은 적절한 메타 클래스를 생성하는 메타 클래스 팩토리를 만드는 것입니다 __repr__(이를 많이 사용하면 좋을 수 있습니다).
skyking


22
class foo(object):
    def __str__(self):
        return "representation"
    def __unicode__(self):
        return u"representation"

10
instances클래스 자체가 아닌 클래스 의 문자열 표현이 변경 됩니다.
tauran

죄송합니다. 게시물의 두 번째 부분이 보이지 않습니다. 위의 방법을 사용하십시오.
안드레이 Gubarev

6
@RobertSiemer 왜? 그의 답변은 특별히 OP의 질문을 목표로하지는 않지만 여전히 도움이됩니다. 그것은 나를 도왔다. 그리고 한눈에 구현 구현을 요구하는 질문이 없습니다. 아마 사람들은이 페이지를 먼저 방문 할 것입니다.
akinuri

14

정의되지 않은 기본 구현 호출 과 같이 첫 번째 옵션 중에서 선택 __repr__하거나 __str__첫 번째로 이동 해야하는 경우 .__str____repr__

커스텀 Vector3 예제 :

class Vector3(object):
    def __init__(self, args):
        self.x = args[0]
        self.y = args[1]
        self.z = args[2]

    def __repr__(self):
        return "Vector3([{0},{1},{2}])".format(self.x, self.y, self.z)

    def __str__(self):
        return "x: {0}, y: {1}, z: {2}".format(self.x, self.y, self.z)

이 예에서는 repr직접 소비 / 실행할 수있는 문자열을 다시 반환하지만 str디버그 출력으로 더 유용합니다.

v = Vector3([1,2,3])
print repr(v)    #Vector3([1,2,3])
print str(v)     #x:1, y:2, z:3

1
__repr__vs 에 대한 요점 __str__은 정확 하지만 인스턴스가 아닌 클래스 객체에 관한 실제 질문에는 대답하지 않습니다.
Björn Pollex

의견을 보내 주셔서 감사합니다. 내 답변을 검토하겠습니다.
user1767754

repr과 str에 대한 구현이 바뀌 었다고 생각합니다.
jspencer

4

Ignacio Vazquez-Abrams의 승인 된 답변 은 매우 옳습니다. 그러나 그것은 파이썬 2 세대에서 나온 것입니다. 현재 Python 3의 업데이트는 다음과 같습니다.

class MC(type):
  def __repr__(self):
    return 'Wahaha!'

class C(object, metaclass=MC):
    pass

print(C)

파이썬 2와 파이썬 3 모두에서 실행되는 코드를 원한다면 6 가지 모듈에서 다룰 것입니다.

from __future__ import print_function
from six import with_metaclass

class MC(type):
  def __repr__(self):
    return 'Wahaha!'

class C(with_metaclass(MC)):
    pass

print(C)

마지막으로 사용자 정의 정적 repr을 원하는 클래스가 하나 있으면 위의 클래스 기반 접근 방식이 효과적입니다. 그러나 여러 개가있는 경우 MC각각 비슷한 메타 클래스를 생성해야하며 번거로울 수 있습니다. 이 경우 메타 프로그래밍을 한 단계 더 발전시키고 메타 클래스 팩토리를 만들면 상황이 좀 더 깨끗해집니다.

from __future__ import print_function
from six import with_metaclass

def custom_class_repr(name):
    """
    Factory that returns custom metaclass with a class ``__repr__`` that
    returns ``name``.
    """
    return type('whatever', (type,), {'__repr__': lambda self: name})

class C(with_metaclass(custom_class_repr('Wahaha!'))): pass

class D(with_metaclass(custom_class_repr('Booyah!'))): pass

class E(with_metaclass(custom_class_repr('Gotcha!'))): pass

print(C, D, E)

인쇄물:

Wahaha! Booyah! Gotcha!

메타 프로그래밍은 일반적으로 매일 필요한 것이 아니라 필요할 때 실제로 그 자리에 닿습니다!


0

모든 훌륭한 답변에 장식으로 내 버전을 추가하기 만하면됩니다.

from __future__ import print_function
import six

def classrep(rep):
    def decorate(cls):
        class RepMetaclass(type):
            def __repr__(self):
                return rep

        class Decorated(six.with_metaclass(RepMetaclass, cls)):
            pass

        return Decorated
    return decorate


@classrep("Wahaha!")
class C(object):
    pass

print(C)

표준 출력 :

Wahaha!

단점 :

  1. C수퍼 클래스 없이는 선언 할 수 없습니다 (아니오 class C:)
  2. C인스턴스는 이상한 파생 __repr__의 인스턴스이므로 인스턴스에 대해 를 추가하는 것이 좋습니다 .
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.