На этом шаге мы попытаемся обосновать необходимость наличия в классе этого метода.
Если опустить метод __str__, то Python в поисках __str__ отыграет назад к результату __repr__. По этой причине мы рекомендуем добавлять в свои классы всегда, по крайней мере, метод __repr__. Это обеспечит полезный результат преобразования строк почти во всех случаях при минимуме работы по его реализации.
Ниже показано, как можно быстро и эффективно добавить в свои классы элементарную поддержку преобразования строк. Для нашего класса Car мы могли бы начать с приведенного ниже метода :
def __repr__(self): return f'Car({self.color!r}, {self.mileage!r})'
Обратите внимание на то, что мы используем флаг преобразования !r, тем самым гарантируя, что в выводимом строковом значении вместо str(self.color) и str(self.mileage) будут использованы repr(self. color) и repr(self.mileage).
Это работает безупречно, но оборотной стороной является то, что мы повторили имя класса в форматной строке. Для того чтобы избежать этого повторения, здесь можно применить трюк с использованием атрибута __calss__.__name__ объекта. Данный атрибут всегда будет зеркально отображать имя класса в виде строки.
Преимущество состоит в том, что вам не придется модифицировать реализацию метода __repr__, когда имя класса изменится. Это позволяет беспрепятственно придерживаться принципа DRY, то есть "не повторяйся":
def __repr__(self): return (f'{self.__class__.__name__}(' f'{self.color!r}, {self.mileage!r})')
Оборотной стороной этой реализации является то, что форматная строка довольно длинная и громоздкая. Но при условии выверенного форматирования вы сможете сохранить свой исходный код аккуратным и соответствующим правилам PEP8.
Во время инспектирования объекта или непосредственного вызова функции repr() с объектом при наличии приведенной выше реализации метода __repr__ мы получаем полезный результат:
>>> repr(my_car) 'Car(red, 37281)'
Печать объекта или вызов функции str() с этим объектом возвращают то же самое строковое значение, потому что заданная по умолчанию реализация __str__ просто вызывает метод __repr__:
>>> print(my_car) 'Car(red, 37281)' >>> str(my_car) 'Car(red, 37281)'
Убеждены, что этот подход обеспечивает наибольшую эффективность и скромный объем работы по его реализации. Более того, этот подход опирается на типовой шаблон в стиле формы для печенья, который можно применять, не особо задумываясь. По этой причине можно всегда стремлитьсяь добавлять в свои классы элементарную реализацию метода __repr__.
Ниже показан законченный пример для Python 3 с дополнительной реализацией метода __str__:
>>> class Car: def __init__(self, color, mileage): self.color = color self.mileage = mileage def __repr__(self): return (f'{self.__class__.__name__}(' f'{self.color!r}, {self.mileage!r})') def __str__(self): return f'{self.color} автомобиль'
На следующем шаге мы рассмотрим отличия Python 2.x.