Шаг 130.
Python: сборник рецептов.
Классы и объекты. Изменение строкового представления экземпляров

    На этом шаге мы рассмотрим использование методов __repr__() и __str__().

Задача

    Вы хотите изменить строки, которые выдаются при выводе или просмотре экземпляров, на что-то более понятное.

Решение

    Чтобы изменить строковое представление экземпляра, определите методы __str__ () и __repr__(). Например:

>>> class Pair:
	def __init__(self, x, y):
		self.x = x
		self.y = y
	def __repr__(self):
		return 'Pair({0.x!r}, {0.y!r})'.format(self)
	def __str__(self):
		return '({0.x!s}, {0.y!s})'.format(self)

	

    Метод __repr__() возвращает кодовое представление экземпляра, и обычно это текст, который нужно ввести, чтобы воссоздать объект. При проверке значений встроенная функция repr() возвращает этот текст (равно как и интерактивный сеанс интерпретатора). Метод __str__() преобразует экземпляр в строку, что и будет выводом функций str() и print(). Например:

>>> # Вывод __repr__()
>>> p = Pair(3, 4)
>>> p
Pair(3, 4)
>>> # Вывод __str__()
>>> print(p)
(3, 4)
>>>

    Реализация этого рецепта также показывает, как различные строковые представления могут быть использованы при форматировании. Конкретнее, специальный код форматирования !r показывает, что вывод __repr__() должен быть использован вместо вызываемого по умолчанию __str__(). Вы можете попробовать это показанным выше классом:

>>> p = Pair(3, 4)
>>> print('p is {0!r}'.format(p))
p is Pair(3, 4)
>>> print('p is {0}'.format(p))
p is (3, 4)
>>> 


Обсуждение

    Определение __repr__() и __str__() часто является хорошей практикой, поскольку может облегчить отладку и вывод экземпляра. Например, просто печатая или логируя экземпляр, программист получит более полезную информацию о содержимом экземпляра.

    Стандартная практика для вывода __repr__() - выдавать такой текст, чтобы eval(repr(x)) == x. Если это невозможно или нежелательно, то обычной практикой будет создание полезного текстового представления, заключенного между < и >. Например:

>>> f = open('sample.txt')
>>> f
<_io.TextIOWrapper name='sample.txt' mode='r' encoding='cp1251'>
>>> 

    Если __str__() не определен, используется вывод __repr__(). Применение в решении format() может показаться немного странным, но код форматирования {0.x} определяет атрибут x аргумента 0. Так, в следующей функции 0 - это аргумент self экземпляра:

def __repr__(self):
    return 'Pair({0.x!r}, {0.y!r})'.format(self)

    В качестве альтернативы этой реализации вы можете также использовать оператор % и такой код:

def __repr__(self):
    return 'Pair(%r, %r)' % (self.x, self.y)

    На следующем шаге мы рассмотрим настройку строкового форматирования.




Предыдущий шаг Содержание Следующий шаг