А теперь модернизируем уже новый класс PatchedPoint
. Реализуйте магические методы _str__ и _repr__.
При преобразовании в строку точка представляется в формате (x, y)
.
Репрезентация же должна возвращать строку для инициализации точки двумя параметрами.
Примечание
Ваше решение должно содержать только классы и функции.
В решении не должно быть вызовов инициализации требуемых классов.
Пример
Ввод
point = PatchedPoint()
print(point)
point.move(2, -3)
print(repr(point))
Вывод
(0, 0)
PatchedPoint(2, -3)
Ввод
first_point = PatchedPoint((2, -7))
second_point = PatchedPoint(7, 9)
print(*map(str, (first_point, second_point)))
print(*map(repr, (first_point, second_point)))
Вывод
(2, -7) (7, 9)
PatchedPoint(2, -7) PatchedPoint(7, 9)
Решение
Эта задача знакомит нас с волшебными методами __str__ и __repr__.
Оба метода преобразует наш объект в удобочитаемый человеком формат. Так в чем же принципиальная разница между ними? Зачем потребовалось делать два разных метода?
Если сформулировать максимально просто, то метод __str__ это то, как должен увидеть объект при выводе пользователь, в то время как __repr__ то, как должен задавать объект разработчик, если хочет получить точно такой же объект. Обратите внимание, что если __repr__ не определен, то вместо него автоматически вызовется __str__.
Посмотреть код
Решение
class Point:
def __init__(self, x, y) -> None:
self.x = x
self.y = y
def move(self, new_x, new_y):
self.x += new_x
self.y += new_y
def length(self, point):
result = ((point.x - self.x) ** 2 + (point.y - self.y) ** 2) ** 0.5
return round(result, 2)
class PatchedPoint(Point):
def __init__(self, *args) -> None:
match len(args):
case 0:
self.x = 0
self.y = 0
case 1:
self.x, self.y = args[0]
case 2:
self.x, self.y = args
def __str__(self) -> str:
string = f'({self.x}, {self.y})'
return string
def __repr__(self) -> str:
string = f'PatchedPoint({self.x}, {self.y})'
return string
Решение
class Point:
def __init__(self, x, y) -> None:
self.x = x
self.y = y
def move(self, new_x, new_y):
self.x += new_x
self.y += new_y
def length(self, point):
result = ((point.x - self.x) ** 2 + (point.y - self.y) ** 2) ** 0.5
return round(result, 2)
class PatchedPoint(Point):
def __init__(self, *args) -> None:
match len(args):
case 0:
super().__init__(0, 0)
case 1:
super().__init__(*args[0])
case 2:
super().__init__(*args)
def __str__(self) -> str:
string = f'({self.x}, {self.y})'
return string
def __repr__(self) -> str:
string = f'PatchedPoint({self.x}, {self.y})'
return string
это не гласная договорённость?
я не искал чем это регламентируется, но, например, в материалах на яндексе есть такое утверждение:
__repr__
вызывается стандартной функциейrepr
и возвращает строку, которая является представлением объекта в формате инициализации. Этот метод может быть также полезен, если необходимо вывести информацию об объектах, когда они являются элементами коллекции.1) скажите, пожалуйста какая разница между двумя вашими блоками кода??
2) можно использовать мой код? или это неверно?
def __repr__(self):
return f'{self.__class__.__name__}{self.x, self.y}’
1) Разница в том, где происходит присводение значений атрибутам – в конструкторе родительского объекта или в дочернем.
2) Можно писать и так. но тогда у наследующего от вашего класса, если не переопределят __repr__ будет корректное имя класса в описании, но некорректный текст. Скорее всего это приведет к тому, что ошибку заметят сильно позже.
то есть правильно использовать??
string = f’PatchedPoint({self.x}, {self.y})’
На мой взгляд, так будет разумнее. Как правильно, я не знаю, буду честен.
По-хорошему, вместо self.x, self.y нужно прописать просто строками типы переменных как это делает python в своей документации.
Спасибо большое)))
ушел искать документацию