Расширенный Python: абстрактный базовый класс и модуль abc
Python предоставляет пакет Abstract Base Class (ABC) для облегчения реализации абстрактных классов, и по понятным причинам этот модуль называется abc
. Абстрактные классы позволяют разработчикам создавать схемы для подклассов, чтобы они имели определенное поведение, поэтому давайте посмотрим, как мы это делаем на примере использования из обычного сценария обработки данных…
Фоновый контекст
Учтите, что мы пишем код для разработки преобразователя формата данных в формат клиента по вашему выбору для вашей системы приема машинного обучения. Поскольку системы данных — это живые организмы, и их внутренняя химия постоянно меняется, и существует множество доступных форматов данных, лучше всего подходить к этой проблеме объектно-ориентированным способом. Итак, давайте создадим класс для нашего преобразователя.
Как упоминалось ранее, две основные проблемы проектирования, с которыми мы сталкиваемся — это несколько форматов данных и возможные изменения во входных данных. Таким образом, чтобы справиться с проблемами, мы хотели бы, чтобы базовый класс, который предоставляет проект, мог бы иметь функциональность в наших различных подклассах преобразователей.
Теперь давайте создадим абстрактный класс для определения схемы нашего базового преобразователя. Имя моего пользовательского формата будет Naruto
.
class NarutoConverter():
def convert(self): pass
def clean_string(self): pass
class JSONtoNaruto(NarutoConverter):
def __init__(self, input_file):
self.__input = input_file
Наш преобразователь имеет два метода convert
для преобразования входного формата в формат Naruto
и метод clean_string
для работы с различным качеством входных строк.
Теперь, поскольку мы создаем абстрактный класс, мы не хотим, чтобы кто-либо создавал экземпляры этого класса, поскольку это всего лишь черновик для будущих преобразователей. Однако то, как мы создаем класс выше, не препятствует созданию экземпляра этого класса.
Вторая проблема с приведенным выше кодом заключается в том, что он не требует, чтобы подклассы реализовывали функциональность методов convert
и clean_string
. В этом случае приведенный выше код в JSONtoNaruto
не выдаст ошибку, даже если методы не реализованы. Давайте посмотрим, как мы можем решить эти проблемы в следующем разделе.
Модуль abc
Теперь давайте посмотрим, как объявить библиотеку NarutoConverter
с abc
и достичь нашей цели.
from abc import ABC, abstractmethod
class NarutoConverter(ABC):
@abstractmethod
def convert(self): pass
@abstractmethod
def clean_string(self): pass
Основной рецепт включает в себя создание абстрактного класса как подкласса ABC
из модуля abc
и использование декоратора @abstractmethod
перед каждым объявлением абстрактного метода. Это помогает применить функциональность абстрактного класса к вашему пользовательскому подклассу. Теперь, если мы попытаемся создать экземпляр класса NarutoConverter
, это вызовет исключение и предотвратит создание экземпляра этого абстрактного класса. Теперь давайте посмотрим на реализацию подкласса JSONtoNaruto
.
class JSONtoNaruto(NarutoConverter):
def __init__(self, input_file):
self.__input = input_file
def convert(self):
naruto_file = self.__input
return naruto_file
def clean_string(self):
clean_str = self.__input.str
return clean_str
В приведенном выше коде мы реализовали оба метода. Если мы запустим код без реализации какого-либо из методов, python вызовет одну из следующих ошибок. Это поведение обеспечивается с помощью декоратора @abstractmethod, который предотвращает создание экземпляра класса без реализации метода.
TypeError: Can't instantiate abstract class JSONtoNaruto with abstract methods convert
TypeError: Can't instantiate abstract class JSONtoNaruto with abstract methods clean_string