Абстрактные классы и методы в Python
В этом уроке вы узнаете об абстрактных классах в Python и о том, как их использовать для создания моделей для других классов.
- Что такое абстрактные классы в Python?
- Пример абстрактного класса Python
- Класс «Employee»
- Класс FulltimeEmployee
- Класс HourlyEmployee
- Класс Payroll
- Основная программа
- Когда использовать абстрактные классы
Что такое абстрактные классы в Python?
В объектно-ориентированном программировании абстрактный класс в Python — это класс, экземпляр которого невозможно создать. Однако вы можете создавать классы, наследующие абстрактный класс. Обычно абстрактный класс используется для создания модели для других классов.
Аналогично, абстрактный метод — это метод без реализации. Абстрактный класс может включать или не включать абстрактные методы. Python не поддерживает напрямую абстрактные классы. Но он предлагает модуль, позволяющий определять абстрактные классы.
Чтобы определить абстрактный класс, используйте модуль abc (abstract base class). Модуль abc предоставляет вам инфраструктуру для определения абстрактных базовых классов.
Например:
from abc import ABC class AbstractClassName(ABC): pass
Чтобы определить абстрактный метод, используйте декоратор @abstractmethod:
from abc import ABC, abstractmethod class AbstractClassName(ABC): @abstractmethod def abstract_method_name(self): pass
Пример абстрактного класса Python
Предположим, вам нужно разработать программу расчета заработной платы для компании.
В компании есть две группы сотрудников: сотрудники, занятые полный рабочий день, и сотрудники, работающие на почасовой основе. Сотрудники, работающие полный рабочий день, получают фиксированную зарплату, а сотрудники, работающие с почасовой оплатой, соответственно получают почасовую оплату за свои услуги.
Программа расчета заработной платы должна распечатать ведомость заработной платы, включающую имена сотрудников и их ежемесячную зарплату.
Чтобы смоделировать программу расчета заработной платы объектно-ориентированным способом, вы можете создать следующие классы: «Employee», «FulltimeEmployee», «HourlyEmployee» и «Payroll».
Для структурирования программы мы будем использовать модули, где каждый класс размещается в отдельном модуле (или файле).
Класс «Employee»
Класс «Employee» представляет сотрудников, работающих полный или почасовой рабочий день. Он должен быть абстрактным классом, поскольку есть только сотрудники, работающие полный рабочий день, и сотрудники, работающие с почасовой оплатой, обычных сотрудников не существует.
Класс «Employee» должен иметь свойство, возвращающее полное имя сотрудника. Кроме того, у него должен быть метод расчета зарплаты. Метод расчета заработной платы должен быть абстрактным.
Следующий пример определяет абстрактный класс Employee:
from abc import ABC, abstractmethod class Employee(ABC): def __init__(self, first_name, last_name): self.first_name = first_name self.last_name = last_name @property def full_name(self): return f"{self.first_name} {self.last_name}" @abstractmethod def get_salary(self): pass
Класс FulltimeEmployee
Класс FulltimeEmployee наследуется от класса Employee. Он предоставит реализацию метода get_salary(). Поскольку штатные сотрудники получают фиксированную зарплату, вы можете инициализировать зарплату в конструкторе класса.
Ниже показан класс FulltimeEmployee:
class FulltimeEmployee(Employee): def __init__(self, first_name, last_name, salary): super().__init__(first_name, last_name) self.salary = salary def get_salary(self): return self.salary
Класс HourlyEmployee
HourlyEmployee также наследуется от класса Employee. Тем не менее, почасовые сотрудники получают оплату в зависимости от рабочего времени и их ставок. Поэтому вы можете инициализировать эту информацию в конструкторе класса.
Чтобы рассчитать зарплату почасовых сотрудников, необходимо перемножить рабочее время и ставки.
Ниже показан класс HourlyEmployee:
class HourlyEmployee(Employee): def __init__(self, first_name, last_name, worked_hours, rate): super().__init__(first_name, last_name) self.worked_hours = worked_hours self.rate = rate def get_salary(self): return self.worked_hours * self.rate
Класс Payroll
Класс Payroll будет иметь метод, который добавляет сотрудника в список сотрудников и распечатывает расчет заработной платы. Поскольку сотрудники, работающие полный рабочий день и почасовые, используют одни и те же интерфейсы (свойство full_time и метод get_salary()), классу Payroll не нужно их различать.
Ниже показан класс Payroll:
class Payroll: def __init__(self): self.employee_list = [] def add(self, employee): self.employee_list.append(employee) def print(self): for e in self.employee_list: print(f"{e.full_name} \t ${e.get_salary()}")
Основная программа
Следующий файл app.py использует классы FulltimeEmployee, HourlyEmployee и Payroll для распечатки заработной платы пяти сотрудников.
from fulltimeemployee import FulltimeEmployee from hourlyemployee import HourlyEmployee from payroll import Payroll payroll = Payroll() payroll.add(FulltimeEmployee('John', 'Doe', 6000)) payroll.add(FulltimeEmployee('Jane', 'Doe', 6500)) payroll.add(HourlyEmployee('Jenifer', 'Smith', 200, 50)) payroll.add(HourlyEmployee('David', 'Wilson', 150, 100)) payroll.add(HourlyEmployee('Kevin', 'Miller', 100, 150)) payroll.print()
Выход:
John Doe $6000 Jane Doe $6500 Jenifer Smith $10000 David Wilson $15000 Kevin Miller $15000
Когда использовать абстрактные классы
На практике абстрактные классы используются для совместного использования кода несколькими тесно связанными классами. В программе расчета заработной платы все подклассы класса «Employee» используют одно и то же свойство «full_name».