Різниця між __str__ та __repr__?


Відповіді:


2723

Алекс добре підсумував, але, на диво, був занадто лаконічним.

По-перше, дозвольте мені ще раз зазначити основні моменти у посту Алекса :

  • Реалізація за замовчуванням марна (важко придумати той, який не був би, але так)
  • __repr__ мета - бути однозначною
  • __str__ мета - бути читабельною
  • Вміст __str__об'єктів містить об'єкти "__repr__

Реалізація за замовчуванням марна

Це здебільшого несподіванка, оскільки параметри Python, як правило, є досить корисними. Однак у цьому випадку встановлення за замовчуванням __repr__може діяти так:

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

було б занадто небезпечно (наприклад, занадто легко потрапити в нескінченну рекурсію, якщо об'єкти посилаються один на одного). Тож Python виганяє. Зауважте, що існує одна умова за замовчуванням: якщо __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)

Але вам потрібно зробити останній крок - переконайтеся, що кожен об’єкт, який ви реалізуєте, має корисну копію, тому такий код може просто працювати. Ось чому виникає річ «eval»: якщо у вас є достатня кількість інформації eval(repr(c))==c, це означає, що ви знаєте все, що вам потрібно знати c. Якщо це досить просто, принаймні нечітко, зробіть це. Якщо ні, то переконайтеся, що у вас є достатня інформація про cвсе одно. Я зазвичай використовую Eval-подібний формату: "MyClass(this=%r,that=%r)" % (self.this,self.that). Це не означає, що ви можете фактично побудувати MyClass або що це правильні аргументи конструктора - але це корисна форма для вираження "це все, що вам потрібно знати про цей екземпляр".

Примітка: я використовував %rвище, ні %s. Ви завжди хочете використовувати repr()[або %rформатування символів, еквівалентно] всередині __repr__реалізації, або ви перемагаєте мета репр. Ви хочете мати можливість диференціювати MyClass(3)і MyClass("3").

Мета __str__- бути читабельною

Зокрема, це не має бути однозначним - зауважте це str(3)==str("3"). Так само, якщо ви реалізуєте абстракцію IP, то його струна виглядає як 192.168.1.1 - це просто чудово. Реалізуючи абстракцію дати / часу, стрічка може бути "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]

НЕ дуже. Зокрема, рядки в контейнері виявляться занадто простими, щоб порушити його представлення рядків. Зважаючи на неоднозначність, пам’ятайте, Python чинить опір спокусі вгадати. Якщо ви хочете описати вище поведінку під час друку списку, просто

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

(ви, ймовірно, також можете зрозуміти, що робити зі словниками.

Підсумок

Реалізуйте __repr__для будь-якого класу, який ви реалізуєте. Це має бути другого характеру. Реалізуйте, __str__якщо ви думаєте, що було б корисно мати версію рядка, яка помиляється на стороні читабельності.


154
Однозначно не згоден з вашою думкою, що налагодження - це не шлях. Для розробки використовують налагоджувач (та / або ведення журналу), для виробництва використовують ведення журналів. За допомогою налагоджувача ви маєте уявлення про все, що пішло не так, коли виникла проблема. Ви можете побачити повну картину. Якщо ви не реєструєте ВСЕ, ви цього не можете отримати. Плюс, якщо ви реєструєте все, що збираєтесь, вам доведеться перебирати тонни даних, щоб отримати необхідне
Самуїл

21
Прекрасна відповідь (за винятком біт про не налагодження). Я просто хотів би додати посилання на цей інший Q&A про str vs unicode в Python 3, який може бути актуальним для обговорення для людей, які перейшли на перехід.
ThatAintWorking

11
плюс1 для налагоджувачів марний, і не варто розміряти ні копійки. Натомість збільште пропускну здатність журналу. І так, це був добре написаний пост. Виявилося, __repr__що мені було потрібно для налагодження. Дякую за твою допомогу.
personal_cloud

7
твій дурний налагоджувач убік, я дізнався% r і це все одно варто проголосувати
Міккі Перлштайн

6
on debugger vs no debugger: не отримуйте таких закріплених думок. У деяких програмах налагодження не є реалістичним, зазвичай це стосується реального часу або коли ваш код виконується лише віддалено на платформі з невеликим доступом або без консолі. У більшості інших випадків буде набагато швидше зупинитися на винятку, щоб дослідити або встановити точку перелому, тому що вам не доведеться пройти тисячі ліній входу в журнал (що забить ваш диск і сповільнить додаток). Нарешті, не завжди можливо ввійти в систему, наприклад, на вбудованих пристроях, там налагоджувач теж ваш друг.
RedGlyph

523

Моє правило: __repr__призначене для розробників, __str__призначене для клієнтів.


2
Це вірно, тому що для obj = uuid.uuid1 (), obj .__ str __ () є "2d7fc7f0-7706-11e9-94ae-0242ac110002", а obj .__ repr __ () є "UUID ('2d7fc7f0-7706-11e9-94ace 027 ') ". Потрібні розробники (значення + походження), тоді як клієнтам потрібна цінність і їм байдуже, як вони її отримали!
Нарен Єллавула

1
Тут клієнт не обов'язково може означати кінцевого споживача. Це клієнт або користувач об'єкта. Тож якщо його SDK, то розробники SDK використовуватимуть __str__так, щоб звичайні розробники мали читабельний об'єкт. З іншого боку, __repr__це для самих розробників SDK.
Шиплу Мокаддім

398

Якщо ви спеціально не працюєте, щоб забезпечити інше, більшість класів не мають корисних результатів для будь-якого:

>>> 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__, НЕ __str__, для елементів, які він містить. І, незважаючи на слова з цього приводу, що зустрічаються в типових документах, навряд чи хтось заважає зробити __repr__об’єкти рядком, який evalможе бути використаний для створення рівного об'єкта (це занадто важко, І не знаючи, як відповідний модуль насправді імпортував, це робить насправді вирівняти неможливо).

Отже, моя порада: зосередьтеся на тому, щоб зробити __str__розумним для людини зрозумілим і не __repr__менш однозначним, навіть якщо це заважає нечіткій недосяжній меті зробити __repr__повернене значення прийнятним як вклад __eval__!


34
У моїх модульних тестах я завжди перевіряю , що має eval(repr(foo))значення об'єкт , рівні foo. Ви маєте рацію, що він не працюватиме поза моїми тестовими випадками, оскільки я не знаю, як імпортується модуль, але це принаймні гарантує, що він працює в якомусь передбачуваному контексті. Я вважаю, що це хороший спосіб оцінки, якщо результат __repr__достатньо явний. Виконання цього завдання в одиничному тесті також допомагає забезпечити __repr__наступні зміни в класі.
Стівен Т. Снайдер

4
Я завжди намагаюся переконатися, що або eval(repr(spam)) == spam(принаймні, у правильному контексті), або eval(repr(spam))підвищує SyntaxError. Таким чином ви уникнете плутанини. (І це майже справедливо для вбудованих і більшості stdlib, за винятком, наприклад, рекурсивних списків, де a=[]; a.append(a); print(eval(repr(a)))вам надається [[Ellipses]]…) Звичайно, я цього не роблю, щоб насправді використовувати eval(repr(spam)) , окрім як перевірка обґрунтованості в одиничних тестах ... але я робити іноді копіювати і вставляти repr(spam)в інтерактивній сесії.
abarnert

Чому б контейнери (списки, кортежі) не використовували __str__для кожного елемента замість __repr__? Мені це здається неправдивим, оскільки я реалізував читабельний __str__у своєму об'єкті, і коли він є частиною списку, я бачу на самому меншій думці __repr__.
SuperGeo

Щойно наткнувся на дратівливу помилку, пов’язану з тим, що eval(repr(x))виходить з ладу навіть для вбудованих типів: class A(str, Enum): X = 'x'підніме SyntaxError на eval(repr(A.X)). Це сумно, але зрозуміло. BTW, eval(str(A.X))насправді працює, але, звичайно, тільки якщо class Aє в обсязі - тому, мабуть, це не дуже корисно.
макс

@SuperGeo Інші відповіді охоплюють це: strелемент використання контейнера, reprтому що [1, 2, 3]! = ["1", "2, 3"].
mtraceur

163

__repr__: представлення об'єкта python зазвичай 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

151

Коротше кажучи, мета __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(); її мета - повернути рядок для друку. Якщо аргумент не заданий, повертає порожній рядок, ''.


1
Яке значення друкованого рядка тут? Чи можете ви поясніть це будь ласка?
Vicrobot

115

Яка різниця між __str__і __repr__в Python?

__str__(читати як "dunder (подвійне підкреслення) рядок") і __repr__(читати як "dunder-repper" (для "представлення")) - це обидва спеціальні методи, що повертають рядки на основі стану об'єкта.

__repr__забезпечує поведінку резервного копіювання, якщо __str__її немає.

Таким чином, спочатку слід написати a, __repr__що дозволяє відновити еквівалентний об'єкт із рядка, який він повертає, наприклад, використовуючи evalабо ввівши його символом для символу в оболонці Python.

У будь-який час пізніше можна написати __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 ) приблизно як:

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

Це означає, що за замовчуванням ви будете друкувати модуль, з якого є об'єкт, ім'я класу та шістнадцяткове представлення його розташування в пам'яті - наприклад:

<__main__.Foo object at 0x7f80665abdd0>

Ця інформація не є дуже корисною, але немає способу вивести, як можна точно створити канонічне зображення будь-якого даного екземпляра, і це краще, ніж нічого, принаймні розповісти нам, як ми могли б однозначно ідентифікувати його в пам'яті.

Як може __repr__бути корисним?

Давайте розглянемо, наскільки це може бути корисно, використовуючи оболонку та datetimeоб’єкти Python . Спочатку нам потрібно імпортувати datetimeмодуль:

import datetime

Якщо ми зателефонуємо datetime.nowв оболонку, ми побачимо все, що потрібно для відтворення еквівалентного об’єкта datetime. Це створюється датою часу __repr__:

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

Якщо ми надрукуємо об’єкт дати, ми побачимо чудовий для людини (фактично, ISO) формат. Це реалізовано датами __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 ). Він досить складний, оскільки всі атрибути, необхідні для відтворення такого об’єкта:

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 ) __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__коли вам потрібне читабельне для людини рядкове подання.


Чи не повинно це бути чимось type(obj).__qualname__?
Соломон Учко

@SolomonUcko так у Python 3, мабуть, так - я шукаю вихідний код, де це реалізовано, і я оновлю свою відповідь цією інформацією, коли збираю її разом.
Аарон Холл

33

На сторінці 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'

Це на пг. №351.
jiten

4
Це своєрідне оману називати reprвідтворювати. Краще подумати про це як представляти.
НельсонГон

31

Крім усіх наведених відповідей, я хотів би додати кілька балів: -

1) __repr__()викликається, коли ви просто пишете ім'я об'єкта на інтерактивній консолі пітона та натискаєте клавішу Enter.

2) __str__()викликається, коли ви використовуєте об'єкт з оператором print.

3) У разі, якщо __str__він відсутній, тоді друкуйте та будь-яку функцію, використовуючи str()виклики __repr__()об'єкта.

4) __str__()контейнерів, коли виклик буде виконувати __repr__()метод його містяться елементів.

5) str()виклик всередині __str__()може потенційно повторюватися без базового випадку та помилки на максимальній глибині рекурсії.

6) __repr__()може викликати, repr()який намагатиметься автоматично уникнути нескінченної рекурсії, замінюючи вже представлений об'єкт на ....


14

Простіше кажучи:

__str__використовується для показу рядкового подання вашого об'єкта, який легко читається іншими.

__repr__використовується , щоб показати строкове представлення на об'єкті.

Скажімо, я хочу створити Fractionклас, у якому рядкове представлення дробу є "(1/2)", а об'єкт (клас дробів) повинен бути представлений як "Дроб (1,2)"

Тож ми можемо створити простий клас дробів:

class Fraction:
    def __init__(self, num, den):
        self.__num = num
        self.__den = den

    def __str__(self):
        return '(' + str(self.__num) + '/' + str(self.__den) + ')'

    def __repr__(self):
        return 'Fraction (' + str(self.__num) + ',' + str(self.__den) + ')'



f = Fraction(1,2)
print('I want to represent the Fraction STRING as ' + str(f)) # (1/2)
print('I want to represent the Fraction OBJECT as ', repr(f)) # Fraction (1,2)

13

Чесно кажучи, eval(repr(obj))ніколи не використовується. Якщо ви виявите, що використовуєте його, вам слід зупинитись, оскільки evalце небезпечно, а рядки - це дуже неефективний спосіб серіалізації ваших об'єктів ( pickleзамість цього використовувати ).

Тому я рекомендую налаштування __repr__ = __str__. Причина полягає в тому, що str(list)заклики reprдо елементів (я вважаю це одним з найбільших недоліків дизайну Python, який не вирішувався Python 3). Фактична repr, ймовірно, не буде дуже корисною як результат print [your, objects].

Щоб визначити це, на мій досвід, найбільш корисним випадком використання reprфункції є введення рядка всередину іншої рядки (з використанням рядкового форматування). Таким чином, вам не доведеться турбуватися про те, щоб уникнути цитат чи чогось іншого. Але зауважте, що тут нічого не evalвідбувається.


19
Я думаю, що це не вистачає суті. Використання eval(repr(obj))- це тест на корисність і основне правило - якщо це відтворить оригінальний об'єкт правильно, то ви маєте гідну __repr__реалізацію. Це не призначено, щоб ви фактично серіалізували об'єкти таким чином.
jwg

7
evalне є по суті небезпечним. Не більше небезпечно , ніж unlink, openабо запису файлів. Чи варто припинити писати у файли, оскільки, можливо, зловмисна атака може використати довільний шлях до файлу, щоб розмістити вміст всередині? Все небезпечно, якщо тупо ними користуються німі люди. Ідіотизм небезпечний. Ефекти Даннінга-Крюгера небезпечні. evalце лише функція.
Луїс Масуеллі

12

З (неофіційного) довідника Wiki Python (копія архіву) від effbot:

__str__" обчислює" неофіційне "рядкове представлення об'єкта. Це відрізняється __repr__тим, що воно не повинно бути дійсним виразом Python: замість цього може використовуватися більш зручне або стисле подання. "


3
__repr__ні в якому разі не потрібно повертати валідне вираження Python.
Божевільний фізик

10

str - Створює новий об’єкт рядка з даного об'єкта.

repr - Повертає канонічне зображення рядка об'єкта.

Відмінності:

str ():

  • робить об'єкт читабельним
  • генерує вихід для кінцевого споживача

repr ():

  • потрібен код, який відтворює об'єкт
  • генерує вихід для розробника

8

Один аспект, якого бракує в інших відповідях. Це правда, що в цілому модель є:

  • Мета __str__: читабельна для людини
  • Мета __repr__: однозначна, можливо машиночитана черезeval

На жаль, ця диференціація є хибною, оскільки Python REPL, а також IPython використовують __repr__для друку об'єктів на консолі REPL (див. Пов'язані питання щодо Python та IPython ). Таким чином, проекти, орієнтовані на інтерактивну роботу консолей (наприклад, Numpy або Pandas), почали ігнорувати вищезазначені правила та __repr__натомість забезпечують зручну для людини реалізацію.


7

З книги Fluent Python :

Основна вимога до об'єкта Python полягає у наданні корисних рядкових представлень про себе, одне використовується для налагодження та ведення журналів, інше для презентації кінцевим користувачам. Ось чому
спеціальні методи існують __repr__і __str__в моделі даних.


5

Відмінні відповіді вже охоплюють різницю між __str__і __repr__, що для мене зводиться до того, що перший читається навіть кінцевим користувачем, а другий є максимально корисним для розробників. Враховуючи це, я вважаю, що реалізація за замовчуванням __repr__часто не вдається досягти цієї мети, оскільки вона опускає інформацію, корисну для розробників.

З цієї причини, якщо у мене досить простий __str__, я, як правило, просто намагаюся отримати найкраще з обох світів чимось на кшталт:

def __repr__(self):
    return '{0} ({1})'.format(object.__repr__(self), str(self))

4

Одне важливе, що потрібно пам’ятати, це те, що контейнери __str__використовують об'єкти, що містяться ' __repr__.

>>> from datetime import datetime
>>> from decimal import Decimal
>>> print (Decimal('52'), datetime.now())
(Decimal('52'), datetime.datetime(2015, 11, 16, 10, 51, 26, 185000))
>>> str((Decimal('52'), datetime.now()))
"(Decimal('52'), datetime.datetime(2015, 11, 16, 10, 52, 22, 176000))"

Python виступає за однозначність щодо читабельності , __str__виклику tupleвикликів, що містяться в об'єктах ' __repr__, «формальне» представлення об'єкта. Хоча формальне представлення важче прочитати, ніж неофіційне, воно є однозначним та надійнішим проти помилок.


Він використовується, __repr__ коли це ( __str__) не визначено! Отже, ви помиляєтесь.
jiten

4

Коротко:

class Demo:
  def __repr__(self):
    return 'repr'
  def __str__(self):
    return 'str'

demo = Demo()
print(demo) # use __str__, output 'str' to stdout

s = str(demo) # __str__ is used, return 'str'
r = repr(demo) # __repr__ is used, return 'repr'

import logging
logger = logging.getLogger(logging.INFO)
logger.info(demo) # use __str__, output 'str' to stdout

from pprint import pprint, pformat
pprint(demo) # use __repr__, output 'repr' to stdout
result = pformat(demo) # use __repr__, result is string which value is 'str'

4
>>> print(decimal.Decimal(23) / decimal.Decimal("1.05"))
21.90476190476190476190476190
>>> decimal.Decimal(23) / decimal.Decimal("1.05")
Decimal('21.90476190476190476190476190')

Коли print()викликається результат, decimal.Decimal(23) / decimal.Decimal("1.05")друкується необроблене число; цей вихід є в рядковій формі, що може бути досягнуто за допомогою __str__(). Якщо ми просто введемо вираз, то отримаємо decimal.Decimalвихід - цей результат знаходиться у формі репрезентації, яку можна досягти за допомогою __repr__(). Усі об'єкти Python мають дві форми виводу. Струнна форма розроблена таким чином, щоб вона читалася людиною. Форма репрезентації призначена для отримання результату, який при подачі інтерпретатора Python (коли це можливо) відтворює представлений об'єкт.


4

__str__можна викликати об’єкт, зателефонувавши str(obj)і повинен повернути людський читабельний рядок

__repr__можна викликати об’єкт за допомогою виклику repr(obj)і повинен повертати внутрішній об'єкт (поля / атрибути об'єкта)

Цей приклад може допомогти:

class C1:pass

class C2:        
    def __str__(self):
        return str(f"{self.__class__.__name__} class str ")

class C3:        
    def __repr__(self):        
         return str(f"{self.__class__.__name__} class repr")

class C4:        
    def __str__(self):
        return str(f"{self.__class__.__name__} class str ")
    def __repr__(self):        
         return str(f"{self.__class__.__name__} class repr")


ci1 = C1()    
ci2 = C2()  
ci3 = C3()  
ci4 = C4()

print(ci1)       #<__main__.C1 object at 0x0000024C44A80C18>
print(str(ci1))  #<__main__.C1 object at 0x0000024C44A80C18>
print(repr(ci1)) #<__main__.C1 object at 0x0000024C44A80C18>
print(ci2)       #C2 class str
print(str(ci2))  #C2 class str
print(repr(ci2)) #<__main__.C2 object at 0x0000024C44AE12E8>
print(ci3)       #C3 class repr
print(str(ci3))  #C3 class repr
print(repr(ci3)) #C3 class repr
print(ci4)       #C4 class str 
print(str(ci4))  #C4 class str 
print(repr(ci4)) #C4 class repr

3

Розуміти __str__та __repr__інтуїтивно та постійно їх розрізняти.

__str__повернути маскуване тіло даного об'єкта для читабельності очей
__repr__повернути справжнє тілесне тіло даного об'єкта (повернути себе) для однозначності ідентифікації.

Дивіться це на прикладі

In [30]: str(datetime.datetime.now())
Out[30]: '2017-12-07 15:41:14.002752'
Disguised in string form

Щодо __repr__

In [32]: datetime.datetime.now()
Out[32]: datetime.datetime(2017, 12, 7, 15, 43, 27, 297769)
Presence in real body which allows to be manipulated directly.

Ми можемо робити арифметичні операції за __repr__результатами зручно.

In [33]: datetime.datetime.now()
Out[33]: datetime.datetime(2017, 12, 7, 15, 47, 9, 741521)
In [34]: datetime.datetime(2017, 12, 7, 15, 47, 9, 741521) - datetime.datetime(2
    ...: 017, 12, 7, 15, 43, 27, 297769)
Out[34]: datetime.timedelta(0, 222, 443752)

якщо застосувати операцію на __str__

In [35]: '2017-12-07 15:43:14.002752' - '2017-12-07 15:41:14.002752'
TypeError: unsupported operand type(s) for -: 'str' and 'str'

Повертає лише помилку.

Ще один приклад.

In [36]: str('string_body')
Out[36]: 'string_body' # in string form

In [37]: repr('real_body')
Out[37]: "'real_body'" #its real body hide inside

Сподіваємось, це допоможе вам створити конкретні підстави, щоб вивчити більше відповідей.


3
  1. __str__повинен повернути об'єкт рядка, тоді як __repr__може повернути будь-який вираз python.
  2. Якщо __str__відсутня реалізація, __repr__функція використовується як резервна. Якщо __repr__відсутня реалізація функції, немає резервного .
  3. Якщо __repr__функція повертає Строкове представлення об'єкта, ми можемо пропустити реалізацію __str__функції.

Джерело: https://www.journaldev.com/22460/python-str-repr-functions


2

__repr__використовується скрізь, за винятком методів printі str(коли __str__визначено a !)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.