Відповіді:
Алекс добре підсумував, але, на диво, був занадто лаконічним.
По-перше, дозвольте мені ще раз зазначити основні моменти у посту Алекса :
__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__
якщо ви думаєте, що було б корисно мати версію рядка, яка помиляється на стороні читабельності.
__repr__
що мені було потрібно для налагодження. Дякую за твою допомогу.
Моє правило: __repr__
призначене для розробників, __str__
призначене для клієнтів.
__str__
так, щоб звичайні розробники мали читабельний об'єкт. З іншого боку, __repr__
це для самих розробників SDK.
Якщо ви спеціально не працюєте, щоб забезпечити інше, більшість класів не мають корисних результатів для будь-якого:
>>> 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__
!
eval(repr(foo))
значення об'єкт , рівні foo
. Ви маєте рацію, що він не працюватиме поза моїми тестовими випадками, оскільки я не знаю, як імпортується модуль, але це принаймні гарантує, що він працює в якомусь передбачуваному контексті. Я вважаю, що це хороший спосіб оцінки, якщо результат __repr__
достатньо явний. Виконання цього завдання в одиничному тесті також допомагає забезпечити __repr__
наступні зміни в класі.
eval(repr(spam)) == spam
(принаймні, у правильному контексті), або eval(repr(spam))
підвищує SyntaxError
. Таким чином ви уникнете плутанини. (І це майже справедливо для вбудованих і більшості stdlib, за винятком, наприклад, рекурсивних списків, де a=[]; a.append(a); print(eval(repr(a)))
вам надається [[Ellipses]]
…) Звичайно, я цього не роблю, щоб насправді використовувати eval(repr(spam))
, окрім як перевірка обґрунтованості в одиничних тестах ... але я робити іноді копіювати і вставляти repr(spam)
в інтерактивній сесії.
__str__
для кожного елемента замість __repr__
? Мені це здається неправдивим, оскільки я реалізував читабельний __str__
у своєму об'єкті, і коли він є частиною списку, я бачу на самому меншій думці __repr__
.
eval(repr(x))
виходить з ладу навіть для вбудованих типів: class A(str, Enum): X = 'x'
підніме SyntaxError на eval(repr(A.X))
. Це сумно, але зрозуміло. BTW, eval(str(A.X))
насправді працює, але, звичайно, тільки якщо class A
є в обсязі - тому, мабуть, це не дуже корисно.
str
елемент використання контейнера, repr
тому що [1, 2, 3]
! = ["1", "2, 3"]
.
__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
Коротше кажучи, мета
__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__
в 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__
?
На сторінці 358 книги Сценарії Питона для обчислювальної науки Ганса Петтера Лангтангена чітко зазначено, що
__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'
repr
відтворювати. Краще подумати про це як представляти.
Крім усіх наведених відповідей, я хотів би додати кілька балів: -
1) __repr__()
викликається, коли ви просто пишете ім'я об'єкта на інтерактивній консолі пітона та натискаєте клавішу Enter.
2) __str__()
викликається, коли ви використовуєте об'єкт з оператором print.
3) У разі, якщо __str__
він відсутній, тоді друкуйте та будь-яку функцію, використовуючи str()
виклики __repr__()
об'єкта.
4) __str__()
контейнерів, коли виклик буде виконувати __repr__()
метод його містяться елементів.
5) str()
виклик всередині __str__()
може потенційно повторюватися без базового випадку та помилки на максимальній глибині рекурсії.
6) __repr__()
може викликати, repr()
який намагатиметься автоматично уникнути нескінченної рекурсії, замінюючи вже представлений об'єкт на ...
.
Простіше кажучи:
__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)
Чесно кажучи, eval(repr(obj))
ніколи не використовується. Якщо ви виявите, що використовуєте його, вам слід зупинитись, оскільки eval
це небезпечно, а рядки - це дуже неефективний спосіб серіалізації ваших об'єктів ( pickle
замість цього використовувати ).
Тому я рекомендую налаштування __repr__ = __str__
. Причина полягає в тому, що str(list)
заклики repr
до елементів (я вважаю це одним з найбільших недоліків дизайну Python, який не вирішувався Python 3). Фактична repr
, ймовірно, не буде дуже корисною як результат print [your, objects]
.
Щоб визначити це, на мій досвід, найбільш корисним випадком використання repr
функції є введення рядка всередину іншої рядки (з використанням рядкового форматування). Таким чином, вам не доведеться турбуватися про те, щоб уникнути цитат чи чогось іншого. Але зауважте, що тут нічого не eval
відбувається.
eval(repr(obj))
- це тест на корисність і основне правило - якщо це відтворить оригінальний об'єкт правильно, то ви маєте гідну __repr__
реалізацію. Це не призначено, щоб ви фактично серіалізували об'єкти таким чином.
eval
не є по суті небезпечним. Не більше небезпечно , ніж unlink
, open
або запису файлів. Чи варто припинити писати у файли, оскільки, можливо, зловмисна атака може використати довільний шлях до файлу, щоб розмістити вміст всередині? Все небезпечно, якщо тупо ними користуються німі люди. Ідіотизм небезпечний. Ефекти Даннінга-Крюгера небезпечні. eval
це лише функція.
З (неофіційного) довідника Wiki Python (копія архіву) від effbot:
__str__
" обчислює" неофіційне "рядкове представлення об'єкта. Це відрізняється __repr__
тим, що воно не повинно бути дійсним виразом Python: замість цього може використовуватися більш зручне або стисле подання. "
__repr__
ні в якому разі не потрібно повертати валідне вираження Python.
Один аспект, якого бракує в інших відповідях. Це правда, що в цілому модель є:
__str__
: читабельна для людини__repr__
: однозначна, можливо машиночитана черезeval
На жаль, ця диференціація є хибною, оскільки Python REPL, а також IPython використовують __repr__
для друку об'єктів на консолі REPL (див. Пов'язані питання щодо Python та IPython ). Таким чином, проекти, орієнтовані на інтерактивну роботу консолей (наприклад, Numpy або Pandas), почали ігнорувати вищезазначені правила та __repr__
натомість забезпечують зручну для людини реалізацію.
З книги Fluent Python :
Основна вимога до об'єкта Python полягає у наданні корисних рядкових представлень про себе, одне використовується для налагодження та ведення журналів, інше для презентації кінцевим користувачам. Ось чому
спеціальні методи існують__repr__
і__str__
в моделі даних.
Відмінні відповіді вже охоплюють різницю між __str__
і __repr__
, що для мене зводиться до того, що перший читається навіть кінцевим користувачем, а другий є максимально корисним для розробників. Враховуючи це, я вважаю, що реалізація за замовчуванням __repr__
часто не вдається досягти цієї мети, оскільки вона опускає інформацію, корисну для розробників.
З цієї причини, якщо у мене досить простий __str__
, я, як правило, просто намагаюся отримати найкраще з обох світів чимось на кшталт:
def __repr__(self):
return '{0} ({1})'.format(object.__repr__(self), str(self))
Одне важливе, що потрібно пам’ятати, це те, що контейнери
__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__
) не визначено! Отже, ви помиляєтесь.
Коротко:
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'
>>> 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 (коли це можливо) відтворює представлений об'єкт.
__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
Розуміти __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
Сподіваємось, це допоможе вам створити конкретні підстави, щоб вивчити більше відповідей.
__str__
повинен повернути об'єкт рядка, тоді як __repr__
може повернути будь-який вираз python.__str__
відсутня реалізація, __repr__
функція використовується як резервна. Якщо __repr__
відсутня реалізація функції, немає резервного .__repr__
функція повертає Строкове представлення об'єкта, ми можемо пропустити реалізацію __str__
функції.Джерело: https://www.journaldev.com/22460/python-str-repr-functions