Когда следует использовать .__repr__() вместо .__str__() в Python?
Оглавление
- Короче говоря, используйте .__repr__() для программистов против .__str__() для пользователей
- Как вы можете получить доступ к строковым представлениям объекта?
- Следует ли вам определять .__repr__() и .__str__() в пользовательском классе?
- Заключение
Смотрите сейчас, к этому уроку прилагается соответствующий видеокурс, созданный командой Real Python. Посмотрите его вместе с письменным руководством, чтобы углубить свое понимание: Когда использовать .__repr__() против .__str__() в Python
Одной из наиболее распространенных задач, выполняемых компьютерной программой, является отображение данных. Программа часто отображает эту информацию пользователю программы. Однако программа также должна предоставлять информацию программисту, который ее разрабатывает и поддерживает. Информация, необходимая программисту об объекте, отличается от того, как программа должна отображать тот же объект для пользователя, и именно здесь возникает .__repr__() против .__str__().
У объекта Python есть несколько специальных методов, которые обеспечивают определенное поведение. Существует два похожих специальных метода, которые описывают объект с помощью строкового представления. Этими методами являются .__repr__() и .__str__(). Метод .__repr__() возвращает подробное описание для программиста, которому необходимо поддерживать и отлаживать код. Метод .__str__() возвращает более простое описание с информацией для пользователя программы.
Методы .__repr__() и .__str__() - это два специальных метода, которые вы можете определить для любого класса. Они позволяют вам управлять тем, как программа отображает объект в нескольких распространенных формах вывода, таких как то, что вы получаете с помощью функции print(), форматированных строк и интерактивных сред.
В этом руководстве вы узнаете, как отличить .__repr__() от .__str__() и как использовать эти специальные методы в определенных вами классах. Эффективное определение этих методов делает классы, которые вы пишете, более удобочитаемыми и простыми в отладке и обслуживании. Итак, когда вам следует выбрать Python's .__repr__() vs .__str__?
Скачать бесплатно: Ознакомьтесь с примером главы из книги "Приемы работы с Python: Книга", в которой показаны лучшие практики Python на простых примерах, которые вы можете подайте заявку немедленно, чтобы написать более красивый + Pythonic код.
<отметить класс="marker-highlight"> Пройдите тест:отметить> Проверьте свои знания с помощью нашего интерактивного теста “Использование .__repr__() против .__str__() в Python”. По завершении вы получите оценку, которая поможет вам отслеживать прогресс в обучении:
<время работы/>
Интерактивная викторина
Использование .__repr__() против .__str__() в PythonВ этом тесте вы проверите свое понимание специальных методов Python dunder repr и dunder str. Эти методы позволяют вам управлять тем, как программа отображает объект, делая ваши классы более удобочитаемыми и простыми в отладке и обслуживании.
Короче говоря: используйте .__repr__() для программистов против .__str__() для пользователей
Классы Python имеют ряд специальных методов. В названиях этих методов есть двойное начальное и конечное подчеркивания. Вы можете неофициально называть их методами dunder из-за двойного подчеркивания в их названиях.
Специальные методы .__repr__() и .__str__() оба возвращают строковые представления объекта. Строковое представление - это строка, отображающая информацию об объекте. Вы можете адаптировать эту информацию для различных аудиторий, таких как пользователи программы или ваши коллеги-программисты.
Как и в случае с другими специальными методами, в названиях которых есть начальное и конечное двойные подчеркивания, вы можете определить эти методы для любого класса.
Причина, по которой существует два метода отображения объекта, заключается в том, что они имеют разные цели:
.__repr__()предоставляет официальное строковое представление объекта, предназначенное для программиста..__str__()предоставляет неформальное строковое представление объекта, предназначенного для пользователя.
Целевой аудиторией строкового представления, возвращаемого .__repr__(), является программист, разрабатывающий и поддерживающий программу. В целом, оно предоставляет подробную и недвусмысленную информацию об объекте. Другим важным свойством официального строкового представления является то, что программист обычно может использовать его для воссоздания объекта, равного исходному.
Метод .__str__() предоставляет строковое представление, предназначенное для пользователя программы, который не обязательно может быть программистом на Python. Таким образом, это представление позволяет любому пользователю понять данные, содержащиеся в объекте. Обычно это проще и понятнее для пользователя.
Примечание: Для обсуждения этих двух специальных методов ознакомьтесь с Подкастом The Real Python: Эпизод 153.
Одним из способов отображения обоих представлений объекта является использование стандартного языка REPL в Python. REPL отобразит строковое представление из .__repr__(), когда вы вычислите строку, в которой есть только объект. Однако встроенная функция print() показывает неформальное строковое представление, возвращаемое .__str__().
Вы можете просмотреть строки, возвращаемые .__repr__() и .__str__() для экземпляра класса datetime в модуле datetime:
>>> import datetime >>> today = datetime.datetime.now() >>> today datetime.datetime(2023, 2, 18, 18, 40, 2, 160890) >>> print(today) 2023-02-18 18:40:02.160890предварительно> кодовый блок>Вы создаете
datetime.datetimeобъект с именемtoday, используя.now(). Этот метод возвращает текущие дату и время. Когда вы вычисляете строку, содержащую только имя переменнойtoday, REPL отображает строковое представление, возвращаемое.__repr__(). Это представление показывает название типа данных и все аргументы, необходимые для повторного создания объекта.При использовании
print()в REPL отображается представление, возвращаемое с помощью.__str__(). В этой строке указан стандартный формат ISO для отображения дат и времени. Таким образом, это не специфичный для Python формат, а стандарт, который используется более широко для представления дат и времени.Часто официальное строковое представление является допустимым выражением Python, которое можно использовать для создания нового объекта с таким же значением. Вы можете подтвердить это с помощью объекта
datetime.datetime, скопировав официальное строковое представление и присвоив ему новое имя. Вы также можете попытаться использовать неформальное строковое представление, но это не сработает:>>> new_date = datetime.datetime(2023, 2, 18, 18, 40, 2, 160890) >>> new_date == today True >>> new_date = 2023-02-18 18:40:02.160890 Traceback (most recent call last): ... File "<input>", line 1 new_date = 2023-02-18 18:40:02.160890 ^ SyntaxError: leading zeros in decimal integer literals are not permitted ...предварительно> кодовый блок>Результат, полученный из
.__repr__()при вычисленииtodayв REPL, создал новый объект, аналогичный исходному.Однако строковое представление из
.__str__(), которое вы получили при использованииprint(), не является допустимым выражением Python, поэтому возникаетSyntaxError.Вы также можете отобразить строковые представления для распространенных встроенных типов данных:
>>> 5 5 >>> print(5) 5 >>> greeting = "How are you?" >>> greeting 'How are you?' >>> print(greeting) How are you?предварительно> кодовый блок>REPL в Python возвращает официальное строковое представление, определенное как
.__repr__(), когда вы вычисляете строку, которая содержит только объект или его имя переменной. Но что происходит сprint()? В приведенных выше примерах официальное строковое представление идентично или почти совпадает с неофициальным строковым представлением, которое возвращаетprint(). Оба представления основаны в основном на литералах, которые вы использовали для создания объектов.Другие встроенные типы данных также имеют одинаковые официальные и неофициальные строковые представления. В этих случаях оба представления равны литералу, используемому для этих объектов.
Примечание: Хотя два строковых представления идентичны литералам для большинства встроенных типов данных, существуют некоторые исключения. Например,
set()является как неофициальным, так и официальным строковым представлением для пустого набора, поскольку литерал{}представляет пустой словарь.Вы можете просмотреть представления для списков и словарей в следующем примере:
>>> [10, 20, 30] [10, 20, 30] >>> print([10, 20, 30]) [10, 20, 30] >>> {"name": "Homer", "role": "author"} {'name': 'Homer', 'role': 'author'} >>> print({"name": "Homer", "role": "author"}) {'name': 'Homer', 'role': 'author'}предварительно> кодовый блок>Эти представления однозначны и позволяют воссоздать объект с тем же значением. Однако они также достаточно понятны для пользователя программы, поскольку передают информацию, содержащуюся в объекте, и не могут быть дополнительно упрощены. Эти объекты не нуждаются в разных строковых представлениях для программиста и пользователя.
Примечание: Вы можете использовать красивую печать в Python для форматирования ваших объектов в еще более удобочитаемом формате, что может быть полезно для отладки.
В этом разделе вы узнали, что официальное строковое представление, возвращаемое
.__repr__(), содержит однозначную информацию об объекте, предназначенную для программиста. Как правило, вы можете использовать это представление для создания объекта с теми же значениями, что и у исходного.В отличие от этого, неформальное строковое представление, возвращаемое
.__str__(), предназначено для пользователя и обычно проще. Литералы, используемые для большинства встроенных типов данных, используются как в качестве неофициальных, так и в качестве официальных строковых представлений для этих типов.В следующем разделе этого руководства вы узнаете о других способах получения двух строковых представлений в Python.
Как вы можете получить доступ к строковым представлениям объекта?
Вы видели, как можно отобразить оба строковых представления в стандартном Python REPL. До этого момента вы использовали специальные методы для этого. Но в целом, вы также можете получить доступ к официальным и неофициальным строковым представлениям, используя встроенные функции
repr()иstr().Когда вы передаете объект в качестве аргумента в
repr()илиstr(), вы вызываете скрытый метод объекта.__repr__()или.__str__(). Вы можете подтвердить это, используя объектdatetime.datetime, который вы создали в предыдущем разделе:>>> import datetime >>> today = datetime.datetime.now() >>> repr(today) 'datetime.datetime(2023, 2, 18, 18, 40, 2, 160890)' >>> today.__repr__() 'datetime.datetime(2023, 2, 18, 18, 40, 2, 160890)' >>> str(today) '2023-02-18 18:40:02.160890' >>> today.__str__() '2023-02-18 18:40:02.160890'предварительно> кодовый блок>Когда вы передаете
todayвстроенной функцииrepr(), программа вызываетtoday.__repr__(). Хотя вы можете вызвать специальный метод напрямую, вызвавtoday.__repr__(), лучше всего использовать встроенную функциюrepr(), поскольку вы не должны обращаться к специальным методам напрямую, когда это возможно. Целью специальных методов является предоставление дополнительной функциональности объекту, а не прямой вызов.Вы можете использовать
str()аналогичным образом. Он вызывает метод.__str__()своего аргумента.Примечание: Это правда, что на первый взгляд использование
str()выглядит аналогично использованиюrepr(). Однако, в то время какrepr()является встроенной функцией,strявляется классом. Таким образом,str()создает экземпляр классаstr, преобразуя его аргумент в строку. Это различие не повлияет на то, как вы используетеstr()иrepr(), поскольку способ их использования зависит от того, что они оба доступны для вызова и не важно, являются ли они функцией или конструктором класса.Вы должны передать объект в качестве аргумента в
repr()иstr(). Однако.__repr__()и.__str__()являются методами и не требуют никаких дополнительных аргументов. Как и во всех методах экземпляра , сам объект передается методу в качестве его первого аргумента. В случае.__repr__()и.__str__()объект также является единственным аргументом, поскольку эти методы не принимают никаких дополнительных аргументов.Вы также можете отобразить строковые представления объекта, используя встроенную функцию
format(), метод string.format(), или f-strings. Вы можете начать с передачиdatetimeобъектаtodayфункцииformat()и метода.format():>>> format(today) '2023-02-18 18:40:02.160890' >>> "{}".format(today) '2023-02-18 18:40:02.160890'предварительно> кодовый блок>По умолчанию они возвращают неформальное строковое представление объекта, которое возвращается с помощью
.__str__(). Вы увидите, как переопределить представление по умолчанию, когда будете изучать f-строки в остальной части этого раздела.Скорее всего, при форматировании строк вы будете использовать f-строки, поскольку это новейшая форма форматирования строк в Python. Вы можете отобразить объект
today, используя f-строки:>>> f"{today}" '2023-02-18 18:40:02.160890'предварительно> кодовый блок>Как и в случае с
format()и.format(), f-строки отображают неформальное строковое представление, которое возвращает.__str__(). Вы можете получить официальное представление строки из.__repr__(), используя флаг преобразования строки"!r"в f-строке:>>> f"{today!r}" 'datetime.datetime(2023, 2, 18, 18, 40, 2, 160890)'предварительно> кодовый блок>Флаг преобразования
"!r"переопределяет значение по умолчанию для f-строк и вызывает метод объекта.__repr__().Вы также можете использовать f-строки со знаком равенства (
=), чтобы отображать как имя переменной, так и ее значение. Этот параметр будет использоваться в основном для целей отладки:>>> f"{today = }" 'today = datetime.datetime(2023, 2, 18, 18, 40, 2, 160890)'предварительно> кодовый блок>Обратите внимание, что при использовании знака равенства в f-строке по умолчанию используется официальное строковое представление, возвращаемое
.__repr__(). Представление, предназначенное для программиста, является наиболее подходящим в данном случае, поскольку знак равенства в f-строках обычно используется для отладки программы.Вы можете переопределить это поведение, используя флаг преобразования
"!s":>>> f"{today = !s}" 'today = 2023-02-18 18:40:02.160890'предварительно> кодовый блок>При использовании преобразования
"!s"в f-строке используется неформальное строковое представление.В следующем разделе вы узнаете, как добавить методы
.__repr__()и.__str___()к определенным вами классам.Следует ли вам определять
.__repr__()и.__str__()в пользовательском классе?Когда вы определяете класс, вы можете определить несколько специальных методов для добавления функциональности классу. Подробнее об определении классов вы можете прочитать в руководстве Объектно-ориентированное программирование (ООП) на Python.
Вы можете изучить строковое представление с помощью пользовательских классов, определив класс с именем
Book. Вы можете использовать скрипт с именемbook.pyдля определения этого класса:# book.py class Book: def __init__(self, title, author): self.title = title self.author = author odyssey = Book("The Odyssey", "Homer") print(odyssey)предварительно> кодовый блок>Вы определяете класс
Bookс помощью метода.__init__(). При инициализации класса требуются два аргумента:titleиauthor.Вы создаете экземпляр этого класса с названием и автором книги "Одиссея" и передаете
odysseyфункцииprint(). Вы используетеprint(), потому что при вычислении строки, содержащей только имя переменной в скрипте, выходные данные не выводятся. Когда вы запускаете этот скрипт, вы получаете следующие выходные данные:$ python book.py <__main__.Book object at 0x1025c4ed0>предварительно> кодовый блок>Этот вывод является строковым представлением объекта по умолчанию, унаследованным от класса
object. Классobjectявляется базовым классом для всех классов Python. Он показывает:
__main__.Book: Название класса и где он определен0x1025c4ed0: Адрес объекта в памятиЭто представление по умолчанию содержит имя класса и адрес памяти, которые отображаются в виде шестнадцатеричного значения. В CPython адрес памяти совпадает с идентификатором объекта. Вы можете определить идентификатор объекта, используя встроенную функцию
id(),, которая возвращает целое число, а не шестнадцатеричное значение.Однако адрес памяти редко бывает полезен. Это представление по умолчанию не предоставляет никакой дополнительной информации об объекте, которая была бы полезна пользователю или программисту.
И
repr(), иstr()возвращают это строковое представление по умолчанию:# book.py class Book: def __init__(self, title, author): self.title = title self.author = author odyssey = Book("The Odyssey", "Homer") print(repr(odyssey)) print(str(odyssey))предварительно> кодовый блок>Вы вызываете
repr(odyssey)иstr(odyssey)и выводите значения, которые они возвращают. На выходе отображается одинаковое представление по умолчанию для обоих значений:$ python book.py <__main__.Book object at 0x100d046d0> <__main__.Book object at 0x100d046d0>предварительно> кодовый блок>Этот вывод подтверждает, что в данный момент доступно только представление по умолчанию.
Вы можете определить специальный метод
.__repr__()для этого класса:# book.py class Book: def __init__(self, title, author): self.title = title self.author = author def __repr__(self): class_name = type(self).__name__ return f"{class_name}(title={self.title!r}, author={self.author!r})" odyssey = Book("The Odyssey", "Homer") print(repr(odyssey)) print(str(odyssey))предварительно> кодовый блок>Метод
.__repr__()не имеет дополнительных параметров, кромеself, и всегда должен возвращать строку. Выходные данные этого кода показывают, что какrepr(odyssey), так иstr(odyssey)возвращают строковое представление, которое вы только что определили:$ python book.py Book(title='The Odyssey', author='Homer') Book(title='The Odyssey', author='Homer')предварительно> кодовый блок>Встроенная функция
repr()вызывает метод.__repr__()объекта. Если в классе не определен метод.__str__(), то вstr()также по умолчанию будет использоваться метод объекта.__repr__().Вы определяете возвращаемое значение для
.__repr__(), которое должно включать имя класса, за которым следуют круглые скобки (()), и два аргумента, необходимые для инициализации класса. Этот формат идеально подходит для официального строкового представления, поскольку он представляет собой допустимое выражение Python, которое может воссоздать объект, равный исходному. По возможности, вам следует использовать этот формат для официального строкового представления.Далее вы можете определить метод
.__str__()для класса:# book.py class Book: def __init__(self, title, author): self.title = title self.author = author def __repr__(self): class_name = type(self).__name__ return f"{class_name}(title={self.title!r}, author={self.author!r})" def __str__(self): return self.title odyssey = Book("The Odyssey", "Homer") print(repr(odyssey)) print(str(odyssey))предварительно> кодовый блок>Вы определяете специальный метод
.__str__(), который не должен иметь никаких дополнительных параметров, кромеself, и должен возвращать строку. Строковым представлением может быть любая строка, которая, по вашему мнению, будет наиболее полезной для пользователя программы. В выходных данных этой версии кода представлены как официальные, так и неофициальные строковые представления в следующем порядке:$ python book.py Book(title='The Odyssey', author='Homer') The Odysseyпредварительно> кодовый блок>Неформальное строковое представление, возвращаемое
.__str__(), отображает только название книги и также не содержит ссылки на название класса. Вы можете настроить неформальное строковое представление в соответствии со своими потребностями:# book.py class Book: def __init__(self, title, author): self.title = title self.author = author def __repr__(self): class_name = type(self).__name__ return f"{class_name}(title={self.title!r}, author={self.author!r})" def __str__(self): return f'"{self.title}" by {self.author}' odyssey = Book("The Odyssey", "Homer") print(repr(odyssey)) print(str(odyssey))предварительно> кодовый блок>Строка, возвращаемая с помощью
.__str__(), теперь содержит название книги в кавычках, за которым следует имя автора. Обратите внимание, что если вы хотите использовать двойные кавычки внутри строки, вы можете использовать одинарные кавычки для обозначения строки. Выходные данные этого кода сначала показывают официальное представление, за которым следует измененное неофициальное строковое представление:$ python book.py Book(title='The Odyssey', author='Homer') "The Odyssey" by Homerпредварительно> кодовый блок>Официальное строковое представление содержит все детали, необходимые программисту, и позволяет вам воспроизвести объект для дальнейшего его изучения. У этого есть несколько основных преимуществ:
- Это делает программу более удобной в обслуживании.
- Это облегчает отладку.
Вы можете использовать выражение в этом строковом представлении для создания объекта с теми же значениями, что и у исходного. Эта функция полезна при отладке, когда вы или ваш коллега-программист копируете объект для дальнейшего его изучения.
Однако неофициальное строковое представление имеет более удобный формат, который лучше подходит для пользователя программы. Такое представление делает вывод более удобным для чтения пользователем.
Примечание: Применяя эти два специальных метода, примите дополнительные меры предосторожности, чтобы гарантировать, что конфиденциальная информация, такая как пароли пользователей, никоим образом не будет раскрыта. Лучше всего пропустить такие атрибуты или, по крайней мере, обезличить их, прежде чем возвращать соответствующую строку.
При определении класса рекомендуется включать официальное строковое представление, определяя
.__repr__(). Используя этот метод, вы избегаете представления по умолчанию, которое в большинстве случаев не очень полезно. Этот метод также предоставляет запасной вариант для неформального строкового представления, который бывает полезен, когда вы можете использовать одно и то же представление для обоих вариантов использования.Если вам нужно отобразить объект для пользователя, вы также можете определить
.__str__(). Этот метод обеспечит вывод, который будет более понятен пользователю.Если вы используете классы данных Python , официальное строковое представление по умолчанию уже включено. Вам не нужно определять
.__repr__()самостоятельно, если только вы не хотите переопределить формат по умолчанию.Теперь вы готовы включить строковые представления в любой класс, который вы определите.
Заключение
В этом руководстве вы узнали разницу между официальным и неофициальным строковым представлением объектов Python. Специальный метод
.__repr__()возвращает официальное строковое представление, которое предназначено для программистов, разрабатывающих и поддерживающих программу. Специальный метод.__str__()возвращает неформальное строковое представление, более удобный формат для пользователя программы.Теперь вы можете различать эти два представления и знать, какого из них ожидать в разных ситуациях. И если вы еще не делали этого, вы никогда не напишете другой класс, не определив, по крайней мере, метод
.__repr__()для обеспечения официального строкового представления.Скачать бесплатно: Ознакомьтесь с примером главы из книги "Приемы работы с Python: Книга", в которой показаны лучшие практики Python на простых примерах, которые вы можете подайте заявку немедленно, чтобы написать более красивый + Pythonic код.
<отметить класс="marker-highlight"> Пройдите тест:отметить> Проверьте свои знания с помощью нашего интерактивного теста “Использование .__repr__() против .__str__() в Python”. По завершении вы получите оценку, которая поможет вам отслеживать прогресс в обучении:
<время работы/>![]()
Интерактивная викторина
Использование .__repr__() против .__str__() в PythonВ этом тесте вы проверите свое понимание специальных методов Python dunder repr и dunder str. Эти методы позволяют вам управлять тем, как программа отображает объект, делая ваши классы более удобочитаемыми и простыми в отладке и обслуживании.
<статус завершения article-slug="python-repr-vs-str" class="btn-group mb-0" data-api-article-bookmark-url="/api/v1/articles/python-repr-vs-str/bookmark/" данные-api-статья-статус завершения-url="/api/v1/articles/python-repr-vs-str/completion_status/"> статус завершения> <кнопка поделиться bluesky-text="Интересная статья на #Python от @realpython.com :" email-body="Ознакомьтесь с этой статьей на Python:%0A%0awкогда следует использовать .__repr__() против .__str__() в Python?" email-subject="Статья по Python для вас" twitter-text="Интересная статья по Python от @realpython:" url="https://realpython.com/python-repr-vs-str /" url-title="Когда следует использовать .__repr__() вместо .__str__() в Python?"> кнопка поделиться>Смотрите сейчас, к этому уроку прилагается соответствующий видеокурс, созданный командой Real Python. Посмотрите его вместе с письменным руководством, чтобы углубить свое понимание: Когда использовать .__repr__() против .__str__() в Python
Back to Top