파이썬 __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'