[python] __str__과 __repr__의 차이점은 무엇입니까?

파이썬 __str____repr__파이썬 의 차이점은 무엇입니까 ?



답변

Alex 는 잘 요약했지만 놀랍게도 너무 간결했습니다.

먼저 Alex의 게시물의 요점을 반복하겠습니다 .

  • 기본 구현은 쓸모가 없습니다 (그렇지 않은 것을 생각하기는 어렵지만 예)
  • __repr__ 목표는 모호하지 않은 것입니다
  • __str__ 목표는 읽을 수있는 것입니다
  • 컨테이너 __str__사용에 포함 된 개체__repr__

기본 구현은 쓸모가 없습니다

파이썬의 기본값이 상당히 유용한 경향이 있기 때문에 이것은 놀랍습니다. 그러나이 경우 기본값은 __repr__다음과 같습니다.

return "%s(%r)" % (self.__class__, self.__dict__)

너무 위험했을 것입니다 (예를 들어, 객체가 서로 참조하면 무한 재귀에 들어가기가 너무 쉽습니다). 그래서 파이썬은 대처합니다. true 인 한 가지 기본값이 있습니다. __repr__가 정의되어 있고 정의되어 __str__있지 않으면 객체는 마치 것처럼 동작합니다 __str__=__repr__.

즉, 구현하는 거의 모든 객체 __repr__에는 객체를 이해하는 데 사용할 수 있는 기능 이 있어야 합니다. 구현 __str__은 선택 사항입니다. “예쁜 인쇄”기능이 필요한 경우 (예 : 보고서 생성기에서 사용) 수행하십시오.

__repr__모호하지 않는 것이 목표

디버거를 믿지 않습니다. 디버거를 사용하는 방법을 모르고 심각하게 사용한 적이 없습니다. 또한 디버거의 가장 큰 결함은 기본 특성이라고 생각합니다. 오랫동안 디버깅 한 대부분의 실패는 멀리 떨어진 은하계에서 일어났습니다. 이것은 내가 종교적 열정으로 벌목을 믿는다는 것을 의미합니다. 로깅은 모든 불합격 서버 시스템의 핵심입니다. 파이썬은 쉽게 로깅 할 수 있습니다 : 어쩌면 프로젝트 특정 래퍼로 필요한 것은

log(INFO, "I am in the weird function and a is", a, "and b is", b, "but I got a null C — using default", default_c)

그러나 마지막 단계를 수행해야합니다. 구현하는 모든 객체에 유용한 repr이 있는지 확인하십시오. 따라서 이와 같은 코드는 작동 할 수 있습니다. 이것이 바로 “평가”가 나오는 이유입니다. 충분한 정보가 있다면 eval(repr(c))==c, 알아야 할 모든 것을 알고 있음을 의미합니다 c. 그것이 퍼지 방식으로 충분히 쉽다면 그렇게하십시오. 그렇지 않은 경우 c어쨌든 충분한 정보가 있는지 확인하십시오 . 나는 보통 eval과 같은 형식을 사용합니다 "MyClass(this=%r,that=%r)" % (self.this,self.that). 실제로 MyClass를 구성 할 수 있거나 이것이 올바른 생성자 인수라는 것을 의미하지는 않지만“이 인스턴스에 대해 알아야 할 모든 것”을 나타내는 유용한 형식입니다.

참고 : %r위가 아닌을 사용했습니다 %s. 구현 내에서 항상 repr()[또는 같은 %r형식의 문자] 를 사용 하거나 __repr__repr의 목표를 이기고 싶습니다. 당신은 구별 할 수 있도록하려면 MyClass(3)MyClass("3").

목표는 __str__읽을 수있는 것입니다

특히, 모호하지 않도록 의도 된 것이 아닙니다 str(3)==str("3"). 마찬가지로 IP 추상화를 구현하는 경우 str을 192.168.1.1처럼 보이는 것이 좋습니다. 날짜 / 시간 추상화를 구현할 때 str은 “2010/4/12 15:35:22″등이 될 수 있습니다. 목표는 프로그래머가 아닌 사용자가 읽기를 원하는 방식으로 나타내는 것입니다. 쓸모없는 자릿수를 잘라 내고 다른 클래스 인 것처럼 보이십시오. 가독성을 지원하는 한 개선 된 것입니다.

컨테이너 __str__사용에 포함 된 개체__repr__

놀랍지 않나요? 그것은 조금이지만 그것들을 사용한다면 얼마나 읽을 수 __str__있습니까?

[moshe is, 3, hello
world, this is a list, oh I don't know, containing just 4 elements]

하지 매우. 특히 컨테이너의 문자열은 문자열 표현을 방해하기가 너무 쉽습니다. 모호함에 직면하여 파이썬은 추측하려는 유혹에 저항합니다. 목록을 인쇄 할 때 위의 동작을 원한다면

print "[" + ", ".join(l) + "]"

(사전에 대해 어떻게해야하는지 알아낼 수도 있습니다.

요약

구현 __repr__한 모든 클래스에 대해 구현하십시오. 이것은 제 2의 본성이어야합니다. __str__가독성 측면에서 잘못된 문자열 버전을 사용하는 것이 유용하다고 생각되면 구현 하십시오.


답변

내 경험 법칙 : __repr__개발자, __str__고객을위한 것입니다.


답변

특별히 보장하기 위해 행동하지 않는 한, 대부분의 수업은 다음 중 하나에 대한 유용한 결과를 얻지 못합니다.

>>> class Sic(object): pass
... 
>>> print str(Sic())
<__main__.Sic object at 0x8b7d0>
>>> print repr(Sic())
<__main__.Sic object at 0x8b7d0>
>>> 

보시다시피, 클래스와 객체를 넘어서는 차이가 없으며 정보도 없습니다 id. 둘 중 하나만 재정의하는 경우 … :

>>> class Sic(object): 
...   def __repr__(object): return 'foo'
... 
>>> print str(Sic())
foo
>>> print repr(Sic())
foo
>>> class Sic(object):
...   def __str__(object): return 'foo'
... 
>>> print str(Sic())
foo
>>> print repr(Sic())
<__main__.Sic object at 0x2617f0>
>>> 

보시 __repr__다시피, 재정의 하면에도 사용 __str__되지만 그 반대도 아닙니다.

알아야 할 다른 중요한 것들 : __str__내장 컨테이너에서 포함 된 항목에 대해 __repr__, NOT을 사용합니다 __str__. 그리고 일반적인 문서에서 발견 된 주제에 대한 단어에도 불구하고, __repr__객체를 eval동일한 객체를 만드는 데 사용할 수있는 문자열로 만드는 사람을 귀찮게하는 사람은 거의 없습니다 (너무 어렵고 관련 모듈을 실제로 가져 오는 방법 을 모릅니다) 불가능하다).

그래서, 내 조언 : 만들기에 초점을 __str__합리적인 사람이 읽을 수있는, 그리고 __repr__만드는 퍼지 달성 할 수없는 목표로 그를 방해이 경우에도, 당신이 가능하게 할 수있는만큼 명백한 __repr__‘에 대한 입력으로 허용 값을 반환 s의 __eval__!


답변

__repr__: 파이썬 객체의 표현은 일반적으로 eval이 해당 객체로 다시 변환합니다.

__str__: 당신이 생각하는 것은 텍스트 형태의 객체입니다.

예 :

>>> s="""w'o"w"""
>>> repr(s)
'\'w\\\'o"w\''
>>> str(s)
'w\'o"w'
>>> eval(str(s))==s
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    w'o"w
       ^
SyntaxError: EOL while scanning single-quoted string
>>> eval(repr(s))==s
True


답변

요컨대, 목표는 __repr__모호하지 않고 __str__읽을 수있는 것입니다.

다음은 좋은 예입니다.

>>> import datetime
>>> today = datetime.datetime.now()
>>> str(today)
'2012-03-14 09:21:58.130922'
>>> repr(today)
'datetime.datetime(2012, 3, 14, 9, 21, 58, 130922)'

repr에 대한이 문서를 읽으십시오.

repr(object)

인쇄 가능한 객체 표현이 포함 된 문자열을 반환합니다. 이것은 변환에 의해 산출 된 값과 같습니다 (역 따옴표). 이 기능을 일반 기능으로 액세스 할 수있는 경우가 종종 있습니다. 많은 유형의 경우이 함수는에 전달 될 때 동일한 값을 가진 객체를 생성하는 문자열을 반환하려고 시도합니다 eval(). 그렇지 않으면 표현은 추가 정보와 함께 객체 유형의 이름을 포함하는 꺾쇠 괄호로 묶인 문자열입니다. 종종 개체의 이름과 주소를 포함합니다. 클래스는 __repr__()메소드 를 정의하여이 함수가 인스턴스에 대해 리턴하는 것을 제어 할 수 있습니다 .

str에 대한 문서는 다음과 같습니다.

str(object='')

멋지게 인쇄 가능한 객체 표현을 포함하는 문자열을 반환합니다. 문자열의 경우 문자열 자체를 반환합니다. 차이점 repr(object)str(object)항상 허용 가능한 문자열을 반환하지는 않는다는 것입니다 eval(). 그것의 목표는 인쇄 가능한 문자열을 반환하는 것입니다. 인수가 없으면 빈 문자열을 반환합니다 ''.


답변

파이썬 __str____repr__파이썬 의 차이점은 무엇입니까 ?

__str__( “dunder (이중 밑줄) 문자열”로 __repr__읽음 ) 및 ( “dunder-repper”( “표현”의 경우)로 읽음)는 모두 객체의 상태에 따라 문자열을 반환하는 특수한 방법입니다.

__repr____str__누락 된 경우 백업 동작을 제공합니다 .

따라서 먼저 파이썬 쉘에서 문자를 __repr__사용 eval하거나 문자를 입력 하여 반환하는 문자열에서 동등한 객체를 다시 인스턴스화 할 수있는를 작성해야합니다 .

나중에 언제든지 __str__필요하다고 생각 될 때 인스턴스의 사용자가 읽을 수있는 문자열 표현을 위해를 작성할 수 있습니다.

__str__

객체를 인쇄하거나 전달하는 경우합니다 format, str.format또는 str하는 경우 다음 __str__메소드가 정의되고, 그 메소드가 호출 될 것이다, 그렇지 않으면 __repr__사용됩니다.

__repr__

__repr__메소드는 내장 함수에 의해 호출되며 repr객체를 리턴하는 표현식을 평가할 때 파이썬 쉘에서 에코됩니다.

에 대한 백업을 제공하므로 __str__하나만 쓸 수 있으면__repr__

다음은 내장 도움말입니다 repr.

repr(...)
    repr(object) -> string

    Return the canonical string representation of the object.
    For most object types, eval(repr(object)) == object.

즉, 대부분의 객체에서로 인쇄 된 내용을 입력 repr하면 동등한 객체를 만들 수 있어야합니다. 그러나 이것은 기본 구현이 아닙니다.

기본 구현 __repr__

기본 객체 __repr__는 ( C Python source )입니다.

def __repr__(self):
    return '<{0}.{1} object at {2}>'.format(
      self.__module__, type(self).__name__, hex(id(self)))

즉, 기본적으로 객체가 속한 모듈, 클래스 이름 및 메모리에서 해당 위치의 16 진수 표현을 인쇄합니다. 예를 들면 다음과 같습니다.

<__main__.Foo object at 0x7f80665abdd0>

이 정보는 그다지 유용하지는 않지만 주어진 인스턴스를 정식으로 표현할 수있는 방법을 도출 할 수있는 방법이 없으며, 적어도 메모리에서 고유하게 식별 할 수있는 방법을 알려주는 것이 좋습니다.

어떻게 __repr__유용 할 수 있습니까?

파이썬 쉘과 datetime객체를 사용하여 얼마나 유용한 지 살펴 보자 . 먼저 datetime모듈 을 가져와야합니다 .

import datetime

datetime.now쉘 을 호출 하면 동등한 datetime 객체를 재생성하는 데 필요한 모든 것을 볼 수 있습니다. 이것은 datetime에 의해 작성됩니다 __repr__.

>>> datetime.datetime.now()
datetime.datetime(2015, 1, 24, 20, 5, 36, 491180)

날짜 / 시간 객체를 인쇄하면 사람이 읽을 수있는 형식 (실제로는 ISO)으로 표시됩니다. 이것은 datetime에 의해 구현됩니다 __str__.

>>> print(datetime.datetime.now())
2015-01-24 20:05:44.977951

__repr__출력 에서 복사하여 붙여 넣은 다음 인쇄 하여 변수에 할당하지 않았기 때문에 잃어버린 객체를 재생성하는 것은 간단 합니다. 다른 객체와 동일한 사람이 읽을 수있는 출력으로 가져옵니다.

>>> the_past = datetime.datetime(2015, 1, 24, 20, 5, 36, 491180)
>>> print(the_past)
2015-01-24 20:05:36.491180

그것들을 어떻게 구현합니까?

개발 중에는 가능한 한 동일한 상태에서 객체를 재현 할 수 있어야합니다. 예를 들어, 이것은 datetime 객체가 정의하는 방식입니다 __repr__( Python source ). 이러한 객체를 재생산하는 데 필요한 모든 속성으로 인해 상당히 복잡합니다.

def __repr__(self):
    """Convert to formal string, for repr()."""
    L = [self._year, self._month, self._day,  # These are never zero
         self._hour, self._minute, self._second, self._microsecond]
    if L[-1] == 0:
        del L[-1]
    if L[-1] == 0:
        del L[-1]
    s = "%s.%s(%s)" % (self.__class__.__module__,
                       self.__class__.__qualname__,
                       ", ".join(map(str, L)))
    if self._tzinfo is not None:
        assert s[-1:] == ")"
        s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
    if self._fold:
        assert s[-1:] == ")"
        s = s[:-1] + ", fold=1)"
    return s

객체가 사람이 읽을 수있는 표현을 갖기를 원하면 __str__다음에 구현할 수 있습니다 . datetime 객체 ( Python source )가 구현 하는 방법은 다음과 같습니다. __str__이미 ISO 형식으로 표시하는 기능이 있기 때문에 쉽게 수행 할 수 있습니다.

def __str__(self):
    "Convert to string, for str()."
    return self.isoformat(sep=' ')

설정 __repr__ = __str__?

이것은 설정을 제안하는 또 다른 대답에 대한 비판입니다 __repr__ = __str__.

설정 __repr__ = __str__어리석은 것은 – __repr__에 대한 대체입니다 __str__하고는 __repr__, 작성해야 디버깅 개발자 사용을 위해 작성 당신은 쓰기 전에 __str__.

__str__객체의 텍스트 표현이 필요한 경우 에만 필요합니다.

결론

__repr__작성하는 객체를 정의 하여 개발할 때 사용할 때와 다른 개발자가 재현 할 수있는 예를 갖도록합니다. __str__사람이 읽을 수있는 문자열 표현이 필요한시기를 정의하십시오 .


답변

Hans Petter Langtangen의 컴퓨팅 과학위한 Python 스크립팅 책 358 페이지에 다음과 같이 명시되어 있습니다.

  • __repr__객체의 완전한 문자열 표현을 목표로;
  • __str__인쇄를위한 좋은 문자열을 반환하는 것입니다.

그래서 저는 그것들을

  • repr = 재생산
  • str = 문자열 (표현)

파이썬을 배울 때 내가 잘못 이해했지만 사용자의 관점에서.

작지만 좋은 예는 다음과 같은 페이지에 있습니다.

In [38]: str('s')
Out[38]: 's'

In [39]: repr('s')
Out[39]: "'s'"

In [40]: eval(str('s'))
Traceback (most recent call last):

  File "<ipython-input-40-abd46c0c43e7>", line 1, in <module>
    eval(str('s'))

  File "<string>", line 1, in <module>

NameError: name 's' is not defined


In [41]: eval(repr('s'))
Out[41]: 's'