Наследование - один из основных принципов объектно-ориентированного программирования. Оно позволяет создавать новые классы на основе существующих, наследуя их атрибуты и методы. Это способствует повторному использованию кода и созданию иерархий классов.
Для создания дочернего класса указывается родительский класс в скобках после имени класса:
# Родительский класс
class Животное:
def __init__(self, имя, возраст):
self.имя = имя
self.возраст = возраст
def описание(self):
return f"{self.имя} - животное, возраст: {self.возраст} лет"
def спать(self):
return f"{self.имя} спит"
def есть(self):
return f"{self.имя} ест"
# Дочерний класс
class Собака(Животное):
def __init__(self, имя, возраст, порода):
# Вызов конструктора родительского класса
super().__init__(имя, возраст)
self.порода = порода
# Новый метод
def лаять(self):
return f"{self.имя} гавкает"
# Переопределение метода
def описание(self):
return f"{self.имя} - собака породы {self.порода}, возраст: {self.возраст} лет"
# Еще один дочерний класс
class Кошка(Животное):
def __init__(self, имя, возраст, цвет):
super().__init__(имя, возраст)
self.цвет = цвет
def мяукать(self):
return f"{self.имя} мяукает"
def описание(self):
return f"{self.имя} - кошка цвета {self.цвет}, возраст: {self.возраст} лет"
# Использование классов
собака = Собака("Бобик", 3, "Овчарка")
кошка = Кошка("Мурка", 2, "Рыжий")
# Унаследованные методы
print(собака.спать())
print(кошка.есть())
# Переопределенные методы
print(собака.описание())
print(кошка.описание())
# Собственные методы
print(собака.лаять())
print(кошка.мяукать())
Python поддерживает множественное наследование, когда класс может наследовать от нескольких родительских классов:
# Первый родительский класс
class Летающий:
def __init__(self, высота=0):
self.высота = высота
def взлететь(self):
self.высота = 100
return f"Объект взлетел на высоту {self.высота} метров"
def приземлиться(self):
self.высота = 0
return "Объект приземлился"
# Второй родительский класс
class Плавающий:
def __init__(self, глубина=0):
self.глубина = глубина
def нырнуть(self):
self.глубина = 10
return f"Объект нырнул на глубину {self.глубина} метров"
def всплыть(self):
self.глубина = 0
return "Объект всплыл"
# Дочерний класс, наследующий от двух родительских
class Утка(Летающий, Плавающий):
def __init__(self, имя):
# Вызов конструкторов обоих родительских классов
Летающий.__init__(self)
Плавающий.__init__(self)
self.имя = имя
def описание(self):
return f"{self.имя} - утка, может летать и плавать"
# Использование множественного наследования
утка = Утка("Дональд")
print(утка.описание())
# Методы от первого родительского класса
print(утка.взлететь())
print(утка.приземлиться())
# Методы от второго родительского класса
print(утка.нырнуть())
print(утка.всплыть())
Метод super() используется для вызова методов родительского класса:
class ТранспортноеСредство:
def __init__(self, марка, модель, год):
self.марка = марка
self.модель = модель
self.год = год
print(f"Создано транспортное средство: {self.марка} {self.модель}")
def описание(self):
return f"{self.марка} {self.модель} ({self.год})"
def завести(self):
return "Транспортное средство заведено"
class Автомобиль(ТранспортноеСредство):
def __init__(self, марка, модель, год, тип_двигателя):
# Вызов конструктора родительского класса через super()
super().__init__(марка, модель, год)
self.тип_двигателя = тип_двигателя
print(f"Добавлен тип двигателя: {self.тип_двигателя}")
def описание(self):
# Вызов метода родительского класса через super()
базовое_описание = super().описание()
return f"{базовое_описание}, двигатель: {self.тип_двигателя}"
def завести(self):
# Вызов метода родительского класса и его расширение
базовое_сообщение = super().завести()
return f"{базовое_сообщение} - автомобиль {self.марка}"
class Электромобиль(Автомобиль):
def __init__(self, марка, модель, год, емкость_батареи):
# Вызов конструктора родительского класса
super().__init__(марка, модель, год, "электрический")
self.емкость_батареи = емкость_батареи
print(f"Добавлена емкость батареи: {self.емкость_батареи} кВт·ч")
def описание(self):
# Цепочка вызовов через super()
базовое_описание = super().описание()
return f"{базовое_описание}, батарея: {self.емкость_батареи} кВт·ч"
def зарядить(self):
return f"Электромобиль {self.марка} заряжается"
# Использование цепочки наследования
электромобиль = Электромобиль("Tesla", "Model S", 2023, 100)
print(электромобиль.описание())
print(электромобиль.завести())
print(электромобиль.зарядить())
Абстрактные классы определяют интерфейс для своих подклассов, но не могут быть инстанцированы напрямую:
from abc import ABC, abstractmethod
# Абстрактный класс
class Фигура(ABC):
def __init__(self, название):
self.название = название
@abstractmethod
def площадь(self):
pass
@abstractmethod
def периметр(self):
pass
def описание(self):
return f"Это {self.название}"
# Конкретные реализации
class Прямоугольник(Фигура):
def __init__(self, ширина, высота):
super().__init__("прямоугольник")
self.ширина = ширина
self.высота = высота
def площадь(self):
return self.ширина * self.высота
def периметр(self):
return 2 * (self.ширина + self.высота)
class Круг(Фигура):
def __init__(self, радиус):
super().__init__("круг")
self.радиус = радиус
def площадь(self):
import math
return math.pi * self.радиус ** 2
def периметр(self):
import math
return 2 * math.pi * self.радиус
# Попытка создать экземпляр абстрактного класса вызовет ошибку
# фигура = Фигура("абстрактная фигура") # TypeError
# Создание экземпляров конкретных классов
прямоугольник = Прямоугольник(5, 3)
круг = Круг(4)
print(прямоугольник.описание())
print(f"Площадь: {прямоугольник.площадь()}")
print(f"Периметр: {прямоугольник.периметр()}")
print(круг.описание())
print(f"Площадь: {круг.площадь():.2f}")
print(f"Периметр: {круг.периметр():.2f}")
В Python используется алгоритм C3 для определения порядка разрешения методов:
class A:
def метод(self):
return "Метод из класса A"
class B(A):
def метод(self):
return "Метод из класса B"
class C(A):
def метод(self):
return "Метод из класса C"
class D(B, C):
pass
# Проверка порядка разрешения методов
print("MRO для класса D:")
for cls in D.__mro__:
print(cls)
# Вызов метода
d = D()
print(d.метод()) # Будет вызван метод из класса B
# Явный вызов метода из определенного класса
print(C.метод(d)) # Вызов метода из класса C
Рассмотрим практические примеры использования наследования:
class Сотрудник:
def __init__(self, имя, фамилия, идентификатор, зарплата):
self.имя = имя
self.фамилия = фамилия
self.идентификатор = идентификатор
self.зарплата = зарплата
def полное_имя(self):
return f"{self.имя} {self.фамилия}"
def описание(self):
return f"Сотрудник: {self.полное_имя()}, ID: {self.идентификатор}"
def рассчитать_зарплату(self):
return self.зарплата
class Менеджер(Сотрудник):
def __init__(self, имя, фамилия, идентификатор, зарплата, бонус, отдел):
super().__init__(имя, фамилия, идентификатор, зарплата)
self.бонус = бонус
self.отдел = отдел
def описание(self):
базовое_описание = super().описание()
return f"{базовое_описание}, Отдел: {self.отдел}"
def рассчитать_зарплату(self):
return self.зарплата + self.бонус
def управлять(self):
return f"{self.полное_имя()} управляет отделом {self.отдел}"
class Разработчик(Сотрудник):
def __init__(self, имя, фамилия, идентификатор, зарплата, язык_программирования, уровень):
super().__init__(имя, фамилия, идентификатор, зарплата)
self.язык_программирования = язык_программирования
self.уровень = уровень
def описание(self):
базовое_описание = super().описание()
return f"{базовое_описание}, Язык: {self.язык_программирования}, Уровень: {self.уровень}"
def программировать(self):
return f"{self.полное_имя()} программирует на {self.язык_программирования}"
def повысить_уровень(self):
уровни = ["Junior", "Middle", "Senior"]
if self.уровень in уровни and уровни.index(self.уровень) < len(уровни) - 1:
новый_уровень = уровни[уровни.index(self.уровень) + 1]
self.уровень = новый_уровень
return f"{self.полное_имя()} повышен до уровня {self.уровень}"
return f"{self.полное_имя()} уже имеет максимальный уровень"
# Использование системы сотрудников
менеджер = Менеджер("Иван", "Петров", "M001", 80000, 20000, "IT")
разработчик = Разработчик("Анна", "Сидорова", "D001", 60000, "Python", "Middle")
# Вывод информации
print(менеджер.описание())
print(f"Зарплата менеджера: {менеджер.рассчитать_зарплату()}")
print(менеджер.управлять())
print(разработчик.описание())
print(f"Зарплата разработчика: {разработчик.рассчитать_зарплату()}")
print(разработчик.программировать())
print(разработчик.повысить_уровень())
Задание 1:
class ТранспортноеСредство:
def __init__(self, марка, модель, год):
self.марка = марка
self.модель = модель
self.год = год
def описание(self):
return f"{self.марка} {self.модель} ({self.год})"
def завести(self):
return "Транспортное средство заведено"
class Автомобиль(ТранспортноеСредство):
def __init__(self, марка, модель, год, объем_двигателя):
super().__init__(марка, модель, год)
self.объем_двигателя = объем_двигателя
def описание(self):
базовое = super().описание()
return f"{базовое}, двигатель {self.объем_двигателя} л"
def ехать(self):
return f"{self.марка} {self.модель} едет"
class Электромобиль(Автомобиль):
def __init__(self, марка, модель, год, емкость_батареи):
super().__init__(марка, модель, год, "электрический")
self.емкость_батареи = емкость_батареи
def описание(self):
базовое = super().описание()
return f"{базовое}, батарея {self.емкость_батареи} кВт·ч"
def зарядить(self):
return f"{self.марка} {self.модель} заряжается"
def ехать(self):
return f"{self.марка} {self.модель} едет тихо на электричестве"
# Пример использования
электромобиль = Электромобиль("Tesla", "Model 3", 2023, 75)
print(электромобиль.описание())
print(электромобиль.завести())
print(электромобиль.ехать())
print(электромобиль.зарядить())
Задание 2:
from abc import ABC, abstractmethod
import math
class Фигура(ABC):
def __init__(self, название):
self.название = название
@abstractmethod
def площадь(self):
pass
@abstractmethod
def периметр(self):
pass
class Квадрат(Фигура):
def __init__(self, сторона):
super().__init__("квадрат")
self.сторона = сторона
def площадь(self):
return self.сторона ** 2
def периметр(self):
return 4 * self.сторона
class Треугольник(Фигура):
def __init__(self, сторона_a, сторона_b, сторона_c):
super().__init__("треугольник")
self.сторона_a = сторона_a
self.сторона_b = сторона_b
self.сторона_c = сторона_c
def площадь(self):
# Формула Герона
p = self.периметр() / 2
return math.sqrt(p * (p - self.сторона_a) * (p - self.сторона_b) * (p - self.сторона_c))
def периметр(self):
return self.сторона_a + self.сторона_b + self.сторона_c
class Круг(Фигура):
def __init__(self, радиус):
super().__init__("круг")
self.радиус = радиус
def площадь(self):
return math.pi * self.радиус ** 2
def периметр(self):
return 2 * math.pi * self.радиус
# Пример использования
фигуры = [
Квадрат(5),
Треугольник(3, 4, 5),
Круг(3)
]
for фигура in фигуры:
print(f"{фигура.название.capitalize()}: площадь = {фигура.площадь():.2f}, периметр = {фигура.периметр():.2f}")
Задание 3:
class Животное:
def __init__(self, имя, возраст):
self.имя = имя
self.возраст = возраст
def описание(self):
return f"{self.имя} - животное, возраст {self.возраст} лет"
def спать(self):
return f"{self.имя} спит"
class Птица(Животное):
def __init__(self, имя, возраст, размах_крыльев):
super().__init__(имя, возраст)
self.размах_крыльев = размах_крыльев
def описание(self):
базовое = super().описание()
return f"{базовое}, размах крыльев {self.размах_крыльев} см"
def летать(self):
return f"{self.имя} летает"
def чирикать(self):
return f"{self.имя} чирикает"
class Рыба(Животное):
def __init__(self, имя, возраст, глубина_обитания):
super().__init__(имя, возраст)
self.глубина_обитания = глубина_обитания
def описание(self):
базовое = super().описание()
return f"{базовое}, глубина обитания {self.глубина_обитания} м"
def плавать(self):
return f"{self.имя} плавает"
def нырять(self):
return f"{self.имя} ныряет на глубину {self.глубина_обитания} м"
class Млекопитающее(Животное):
def __init__(self, имя, возраст, температура_тела):
super().__init__(имя, возраст)
self.температура_тела = температура_тела
def описание(self):
базовое = super().описание()
return f"{базовое}, температура тела {self.температура_тела}°C"
def греться(self):
return f"{self.имя} греется на солнце"
def выкармливать(потомство):
return f"{self.имя} выкармливает потомство молоком"
# Пример использования
птица = Птица("Синица", 2, 15)
рыба = Рыба("Окунь", 3, 10)
млекопитающее = Млекопитающее("Собака", 5, 38)
животные = [птица, рыба, млекопитающее]
for животное in животные:
print(животное.описание())
if isinstance(животное, Птица):
print(животное.летать())
print(животное.чирикать())
elif isinstance(животное, Рыба):
print(животное.плавать())
print(животное.нырять())
elif isinstance(животное, Млекопитающее):
print(животное.греться())
print(животное.выкармливать("щенки"))
print()
Задание 4:
class Устройство:
def __init__(self, бренд, модель, год_выпуска):
self.бренд = бренд
self.модель = модель
self.год_выпуска = год_выпуска
self.включено = False
def описание(self):
return f"{self.бренд} {self.модель} ({self.год_выпуска})"
def включить(self):
self.включено = True
return f"{self.бренд} {self.модель} включен"
def выключить(self):
self.включено = False
return f"{self.бренд} {self.модель} выключен"
class Смартфон(Устройство):
def __init__(self, бренд, модель, год_выпуска, диагональ_экрана):
super().__init__(бренд, модель, год_выпуска)
self.диагональ_экрана = диагональ_экрана
self.приложения = []
def описание(self):
базовое = super().описание()
return f"{базовое}, экран {self.диагональ_экрана} дюймов"
def установить_приложение(self, приложение):
self.приложения.append(приложение)
return f"Приложение {приложение} установлено"
def позвонить(self, номер):
if not self.включено:
return "Сначала включите устройство"
return f"Звонок на номер {номер}"
class Ноутбук(Устройство):
def __init__(self, бренд, модель, год_выпуска, объем_памяти):
super().__init__(бренд, модель, год_выпуска)
self.объем_памяти = объем_памяти
self.открытые_программы = []
def описание(self):
базовое = super().описание()
return f"{базовое}, память {self.объем_памяти} ГБ"
def открыть_программу(self, программа):
self.открытые_программы.append(программа)
return f"Программа {программа} открыта"
def работать(self):
if not self.включено:
return "Сначала включите устройство"
return f"Работа с программами: {', '.join(self.открытые_программы)}"
class Планшет(Устройство):
def __init__(self, бренд, модель, год_выпуска, тип_сенсора):
super().__init__(бренд, модель, год_выпуска)
self.тип_сенсора = тип_сенсора
self.заряд = 100
def описание(self):
базовое = super().описание()
return f"{базовое}, сенсор {self.тип_сенсора}"
def использовать_сенсор(self):
if not self.включено:
return "Сначала включите устройство"
return f"Используется {self.тип_сенсора} сенсор"
def проверить_заряд(self):
return f"Уровень заряда: {self.заряд}%"
# Пример использования
смартфон = Смартфон("Apple", "iPhone 14", 2022, 6.1)
ноутбук = Ноутбук("Dell", "XPS 13", 2023, 16)
планшет = Планшет("Samsung", "Galaxy Tab", 2022, "емкостный")
устройства = [смартфон, ноутбук, планшет]
for устройство in устройства:
print(устройство.описание())
print(устройство.включить())
if isinstance(устройство, Смартфон):
print(устройство.установить_приложение("Калькулятор"))
print(устройство.позвонить("123-456-7890"))
elif isinstance(устройство, Ноутбук):
print(устройство.открыть_программу("Visual Studio Code"))
print(устройство.работать())
elif isinstance(устройство, Планшет):
print(устройство.использовать_сенсор())
print(устройство.проверить_заряд())
print(устройство.выключить())
print()