В Python наследование классов работает следующим образом. Класс наследник берет весь функционал родительского класса, и позволяет нам добавлять новый функционал. В этой статье мы с вами разберемся на примерах, как использовать наследование классов.
Синтаксис наследования в Python
class BaseClass:
Тело базового класса
class SubBaseClass(BaseClass):
Тело класса наследника
Как видите, класс SubBaseClass() получает функционал родительского класса BaseClass, и при этом в классе наследнике, мы можем дополнить родительский класс требуемым функционалом. То есть вся суть ООП в Python, как и в любом другом языке, заключается в многоразовости использования кода.
Пример наследования класса
Разберем еще один пример наследования класса. Многоугольник — это фигура которая имеет замкнутую форму, с 3 или более сторонами. У нас есть класс Polygon.
class Polygon:
def __init__(self, no_of_sides):
self.n = no_of_sides
self.sides = [0 for i in range(no_of_sides)]
def inputSides(self):
self.sides = [float(input("Enter side "+str(i+1)+" : ")) for i in range(self.n)]
def dispSides(self):
for i in range(self.n):
print("Side",i+1,"is",self.sides[i])
- Атрибут n содержит количество сторон
- Атрибут sides содержит значения сторон
- Метод inputSides() принимает величину каждой стороны
- Метод dipSides() отображает эти длины сторон
Отлично, с этим разобрались. Теперь рассмотрим, как можно наследовать родительский класс. Как все мы знаем, треугольник имеет три стороны, и соответственно он тоже является многоугольником. Определим для него класс Triangle.
class Triangle(Polygon):
def __init__(self):
Polygon.__init__(self,3)
def findArea(self):
a, b, c = self.sides
# calculate the semi-perimeter
s = (a + b + c) / 2
area = (s*(s-a)*(s-b)*(s-c)) ** 0.5
print('The area of the triangle is %0.2f' %area)
Так как наш новый класс Triangle() наследник родительского класса Poligon(), соответственно нам не нужно заново определять атрибуты(та самая многоразовость кода). Так же в нашем классе наследнике появился и новый метод findArea(), которая собственно ищет и печатает площадь треугольника. Ниже приведен полный листинг кода.
class Polygon:
def __init__(self, no_of_sides):
self.n = no_of_sides
self.sides = [0 for i in range(no_of_sides)]
def inputSides(self):
self.sides = [float(input("Введите сторону: "+str(i+1)+" : ")) for i in range(self.n)]
def dispSides(self):
for i in range(self.n):
print("Сторона",i+1,"равна",self.sides[i])
class Triangle(Polygon):
def __init__(self):
Polygon.__init__(self,3)
def findArea(self):
a, b, c = self.sides
# calculate the semi-perimeter
s = (a + b + c) / 2
area = (s*(s-a)*(s-b)*(s-c)) ** 0.5
print('Площадь треугольника{}'.format(area))
t = Triangle()
t.inputSides()
t.dispSides()
t.findArea()
Результат выполнения:
Введите сторону: 1 : 4
Введите сторону: 2 : 6
Введите сторону: 3 : 9
Сторона 1 равна 4.0
Сторона 2 равна 6.0
Сторона 3 равна 9.0
Площадь треугольника 9.56229574945264
Закрепим полученную информацию. В приведенном примере, мы наглядно видим, что хоть методы inputSides() и dipSides() не определены для класса Triangle(), мы смогли их использовать.
Переопределение метода в Python
В приведенном примере, возможно вы уже обратили внимание, что метод __init__() так же был определен и в классе Triangle(). Когда мы определяем тот же метод в классе наследнике, то происходит переопределение метода. Это означает, что теперь метод __init__() определенный в классе Triangle() имеет предпочтение перед тем же методом в классе Polygon().
Но, не всегда вышеописанный вариант является правильным. Лучшим вариантом в данном случае, использовать встроенную функцию super().
super().__init__(3)
Данный является эквивалентным
Polygon.__init__(self,3)
Встроенные функции isinstance() и issubclass() можно использовать для проверка наследства. Функция isinstance() вернет True, если объект является экземпляром класса, или производных от родительского класса.