В рамках первого поста об ООП на Python мы уже рассматривали метод __init__. Все три эти метода (__str__, __repr__ и __init__), как нетрудно заметить, объединяют по два нижних подчеркивания до и после собственно названия метода. Такой синтаксис обозначает так называемые магические (или dunder - от английского “double under(scores)” - “двойное нижнее подчёркивание”) методы. Они используются для определения специального поведения объектов и вызываются во время использования стандартных операций (сложение, вычитание, доступ к атрибутам и др.).

Метод __str__(). Наверняка вам доводилось создать объект какого-нибудь класса и сразу же этот объект распечатать методом print(). Чаще всего результат выглядел немного загадочно. Давайте создадим свой собственный класс и попробуем распечатать его объект.

Используем класс футбольного клуба из предыдущего поста:


class FootballClub:

    def __init__(self, name, description=""):
        self.name = name
        self.description = description

    def describe_club(self):
        msg = f"{self.name}: {self.description}"
        print(msg)

club = FootballClub(“Манчестер Юнайтед”, “Манчестер, Англия”)
print(club)


Вместо того, чтобы вызвать метод describe_club(), мы просто распечатаем вновь созданный объект нашего класса. Результат получается примерно таким:

<__main__.FootballClub object at 0x1050effd0>


Если явным образом не оповестить Python о том, как должно выглядеть представление объекта в виде строки, будет распечатано сообщение, содержащее следующую информацию:

• Имя запускаемого файла • Имя класса, который использовался для создания объекта • Ячейка памяти, в которой хранится объект.

Эта информация бывает полезна в процессе отладки кода, когда нужна заниматься поиском и устранением багов, но простому пользователю она мало о чем говорит. И выглядит, откровенно говоря, не очень читабельно для неподготовленного человека. Метод __str__() позволяет переопределить, что должно выводиться на печать, когда по отношению к объекту класса используется метод print().

Переопределим метод __str__() для нашего класса:


class FootballClub:

    def __init__(self, name, description=""):
        self.name = name
        self.description = description

    def describe_club(self):
        msg = f"{self.name}: {self.description}"
        print(msg)

    def __str__(self):
        return self.name


club = FootballClub("Манчестер Юнайтед", "Манчестер, Англия")
print(club)


И результат выполнение кода теперь выглядит куда дружелюбнее:

Манчестер Юнайтед


Метод __str__() используется не только для вывода строк на печать в терминале. Многие панели управления “ищут” именно __str__() для отображения данных, связанных с экземплярами того или иного класса. Так, к примеру, происходит в админ панели Django, поэтому в большинстве случаев метод __str__() определен в классах моделей.

Рассмотрим пример из официального туториала по созданию приложений на Django. В нём разбирается пример класса модели Question - вопроса в рамках приложения для проведения анкетирования. Код модели выглядит следующим образом:


class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date_published')

    def __str__(self):
        return self.question_text