[python] __str__과 __repr__의 차이점은 무엇입니까?
Alex 는 잘 요약했지만 놀랍게도 너무 간결했습니다.
먼저 Alex의 게시물 에서 요점을 반복하겠습니다 .
- 기본 구현은 쓸모가 없습니다(그렇지 않을 것이라고 생각하기 어렵지만 예)
__repr__
목표는 모호하지 않은 것입니다__str__
목표는 읽을 수 있습니다- 컨테이너의
__str__
사용 포함된 개체'__repr__
기본 구현은 쓸모가 없습니다.
Python의 기본값은 상당히 유용한 경향이 있기 때문에 이것은 대부분 놀라운 일입니다. 그러나 이 경우 기본값이 있으면 다음 __repr__
과 같이 작동합니다.
return "%s(%r)" % (self.__class__, self.__dict__)
너무 위험했을 것입니다(예를 들어, 객체가 서로를 참조하는 경우 무한 재귀에 들어가기가 너무 쉽습니다). 그래서 파이썬은 쫓겨납니다. true인 기본값이 하나 있다는 점에 유의하십시오. __repr__
정의되고 정의 __str__
되지 않은 경우 객체는 마치 처럼 동작합니다 __str__=__repr__
.
즉, 간단히 말해서 구현하는 거의 모든 객체 __repr__
에는 객체를 이해하는 데 사용할 수 있는 기능이 있어야 합니다. 구현 __str__
은 선택 사항입니다. "예쁜 인쇄" 기능이 필요한 경우 수행합니다(예: 보고서 생성기에서 사용).
의 목표는 __repr__
모호하지 않게 하는 것입니다.
바로 나가서 말하겠습니다. 저는 디버거를 믿지 않습니다. 나는 디버거를 어떻게 사용하는지 전혀 모르고 진지하게 사용한 적이 없습니다. 또한 디버거의 가장 큰 결함은 기본 특성에 있다고 생각합니다. 내가 디버그하는 대부분의 오류는 아주 오래전에 멀리 떨어진 은하계에서 발생했습니다. 이것은 내가 종교적 열정으로 벌목을 믿는다는 것을 의미합니다. 로깅은 모든 적절한 화재 및 망각 서버 시스템의 생명선입니다. Python을 사용하면 쉽게 기록할 수 있습니다. 일부 프로젝트 특정 래퍼를 사용하면
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
그렇지 않은 경우 어쨌든 충분한 정보를 가지고 있는지 확인하십시오 . 나는 보통 평가와 같은 형식을 사용합니다: "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__(self): return 'foo'
...
>>> print(str(Sic()))
foo
>>> print(repr(Sic()))
foo
>>> class Sic(object):
... def __str__(self): 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__
__eval__