Давайте расширим функционал класса, написанного вами в задаче «Классная точка 2.0».
Создайте класс PatchedPoint
— наследника уже написанного вами Point
.
Требуется реализовать следующие виды инициализации нового класса:
- параметров не передано — координаты точки равны 0;
- передан один параметр — кортеж с координатами точки;
- передано два параметра — координаты точки.
Примечание
Ваше решение должно содержать только классы и функции.
В решении не должно быть вызовов инициализации требуемых классов.
Пример
Ввод
point = PatchedPoint()
print(point.x, point.y)
point.move(2, -3)
print(point.x, point.y)
Вывод
0 0
2 -3
Ввод
first_point = PatchedPoint((2, -7))
second_point = PatchedPoint(7, 9)
print(first_point.length(second_point))
print(second_point.length(first_point))
Вывод
16.76
16.76
Решение
В этой задаче мы знакомимся с наследованием. Ничего сложного, но есть нюансы. Нюанс связан с вопросом нужно ли использовать функцию super() или можно обойтись без нее?
Ответ на этот вопрос довольно простой. Если вы точно знаете что родительский __init__() не содержит никаких манипуляций с данными, и уверены, что инициализируете в наследуемом классе все необходимые для работы класса переменные, то такой необходимости нет. В общем же случае, использование родительской инициализации всегда безопасней.
Преимущества использования super()
- Автоматическое разрешение методов и поддержка множественного наследования: super() более удобен в использовании в случае множественного наследования, где класс имеет несколько родителей, так как позволяет автоматически определить, какой именно метод следует вызвать в цепочке наследования. Это полезно и в тех случаях, если класс имеет множество родителей.
- Более гибкий код: Если вы измените порядок классов в цепочке наследования,
super()
автоматически учтет эти изменения, в то время как явное указание имени родительского класса может потребовать изменений в коде.
Я привожу два варианта решения – с наивной инициализацией, когда мы не вызываем родительский метод __init__(), и инициализацию с помощью родительского __init__().
Посмотреть код
Решение
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
Решение
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)