Для чего применяются абстрактные методы python
Перейти к содержимому

Для чего применяются абстрактные методы python

  • автор:

ООП. Абстрактный класс. Декомпозиция программы.

Абстрактным называется класс, который содержит один и более абстрактных методов. Абстрактным называется объявленный, но не реализованный метод. Абстрактные классы не могут быть инстанциированы, от них нужно унаследовать, реализовать все их абстрактные методы и только тогда можно создать экземпляр такого класса.

В python существует стандартная библиотека abc, добавляющая в язык абстрактные базовые классы (АБК). АБК позволяют определить класс, указав при этом, какие методы или свойства обязательно переопределить в классах-наследниках.

Возьмем для примера, шахматы. У всех шахматных фигур есть общий функционал, например — возможность фигуры ходить и быть отображенной на доске. Исходя из этого, мы можем создать абстрактный класс Фигура, определить в нем абстрактный метод (в нашем случае — ход, поскольку каждая фигура ходит по-своему) и реализовать общий функционал (отрисовка на доске).

from abc import ABC, abstractmethod class ChessPiece(ABC): # общий метод, который будут использовать все наследники этого класса def draw(self): print("Drew a chess piece") # абстрактный метод, который будет необходимо переопределять для каждого подкласса @abstractmethod def move(self): pass 
a = ChessPiece() # Если мы попытаемся инстанциировать данный класс, логично получим ошибку. 
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) in () ----> 1 a = ChessPiece() # Если мы попытаемся инстанциировать данный класс, логично получим ошибку. TypeError: Can't instantiate abstract class ChessPiece with abstract methods move

Как видите, система не дает нам создать экземпляр данного класса. Теперь нам необходимо создать конкретный класс, например, класс ферзя, в котором мы реализуем метод move.

class Queen(ChessPiece): def move(self): print("Moved Queen to e2e4") # Мы можем создать экземпляр класса q = Queen() # И нам доступны все методы класса q.draw() q.move() 
Drew a chess piece Moved Queen to e2e4

Обратите внимание, абстрактный метод может быть реализован сразу в абстрактном классе, однако, декоратор abstractmethod, обяжет программистов, реализующих подкласс либо реализовать собственную версию абстрактного метода, либо дополнить существующую. В таком случае, мы можем переопределять метод как в обычном наследовании, а вызывать родительский метод при помощи super().

from abc import ABC, abstractmethod class Basic(ABC): @abstractmethod def hello(self): print("Hello from Basic class") class Advanced(Basic): def hello(self): super().hello() print("Enriched functionality") a = Advanced() a.hello() 
Hello from Basic class Enriched functionality

Таким образом, используя концепцию абстрактных классов, мы можем улучшить качество архитектуры приложения, уменьшить объем работы и при этом, обеспечить легкость дальнейшей поддержки кода.

Декомпозиция программы на модули

Модули и пакеты в Python – это прекрасные инструменты для управления сложностью в программном проекте.

Создадим модуль с именем simplemath.py, который будет содержать функции для выполнения простых арифметических действий.

Создадим ещё один модуль worker.py, который будет использовать функции из simplemath.py. Если мы хотим импортировать все функции, то оператор import для нас отлично подойдет. Это будет выглядеть так.

# представим, что эта ячейка - текстовый редактор, который мы сохраним под именем simplemath.py def add(a, b): return a + b def sub(a, b): return a - b def mul(a, b): return a * b def div(a, b): return a / b 
# представим, что эта ячейка - текстовый редактор, который мы сохраним под именем simplemath.py #import simplemath #from simplemath inpord add,sub,mul,div #print(simplemath.add(1, 2)) # = 3 #print(simplemath.sub(1, 2)) # = -1 #print(simplemath.mul(1, 2)) # = 2 #print(simplemath.div(1, 2)) # = 0.5 

Задачи:

Задача 1:

В файле вам даны 3 класса A , B , C , имеющие сходный (но не одинаковый) интерфейс. Вам необходимо создать абстрактный базовый класс Base и построить корректную схему наследования. При выполнении следует избегать дублирования кода, и стараться следовать SOLID принципам ООП.

Задача 2:

В файле вам дана программа. Необходимо провести её рефакторинг.

Для работы программы необходима библиотека PyGame. В открывшемся окне программы доступны следующие команды управления:

  • — показать справку по командам
  • — рестарт
  • — пауза, снять/поставить
  • — увеличить количество точек «сглаживания»
  • — уменьшить количество точек «сглаживания»
  • — добавить «опорную» точку

По умолчанию при старте программы «опорные» точки отсутствуют и программа находится в состоянии паузы (движение кривой выключено). Для добавления точек сделайте несколько кликов левой клавишей мыши в любом месте окна программы. Отрисовка кривой произойдет, когда точек на экране станет больше двух. Нажмите клавишу , чтобы включить движение кривой.

  1. Изучить документацию к библиотеке pygame и код программы. Понять механизм работы программы (как происходит отрисовка кривой, перерасчет точек сглаживания и другие нюансы реализации программы)
  2. Провести рефакторниг кода, переписать программу в ООП стиле с использованием классов и наследования. Реализовать класс 2-мерных векторов Vec2d . В классе следует определить методы для основных математических операций, необходимых для работы с вектором. Добавить возможность вычислять длину вектора с использованием функции len(a) и метод int_pair , который возвращает кортеж из двух целых чисел (текущие координаты вектора).

Реализовать класс замкнутых ломаных Polyline с методами отвечающими за добавление в ломаную точки ( Vec2d ) c её скоростью, пересчёт координат точек ( set_points ) и отрисовку ломаной ( draw_points ). Арифметические действия с векторами должны быть реализованы с помощью операторов, а не через вызовы соответствующих методов.

Реализовать класс Knot (наследник класса Polyline ), в котором добавление и пересчёт координат инициируют вызов функции get_knot для расчёта точек кривой по добавляемым «опорным» точкам.

Все классы должны быть самостоятельными и не использовать внешние функции.

Задача 3* ДНК

Реализуйте классы для ДНК (двойная цепочк) и РНК (одинарная цепочка). Данные структуры данных должны поддерживать следующие возможности:

Умножение РНК

1. Создавать структуру из строк. Обратите внимание, что в ДНК встречаются только азотистые основания ATGC, а в РНК (AUGC) поэтому если во входной строке содержались другие символы, необходимо поднимать ошибку (Exception). 2. Поддерживают индексацию. РНК по индексу возвращает i-ое азотистое основание, ДНК — пару азотистых оснований (соответствующие первой и второй цепочке) 3. РНК может возвращать комплиментарную ДНК (каждому азотистому основанию из РНК соответсвует соответсвующее основание для первой цепочки ДНК: AT , UA , GC , CG . Вторая цепочка ДНК строится комплиментарной первой строчке ДНК: AT , TA , GC , CG ) 4. РНК, как и ДНК, могут складываться путем склеивания («AUUGAACUA» + «CGGAAA» = «AUUGAACUACGGAAA»). У ДНК склеиваются соответствующие цепочки ([«ACG», «TGC»] + [«TTTAAT», «AAATTA»] = [«ACGTTTAAT», «TGCAAATTA»]) 5. РНК могут перемножаться друг с другом: каждое азотистое основание результирующей РНК получается случайным выбором одного из двух соответсвующих родительских азотистых оснований. Если одна из цепочек длиннее другой, то перемножение происходит с начала, когда одна из цепочек закончится оставшийся хвост другой переносится без изменений. 6. ДНК могут перемножаться друг с другом: ПЕРВЫЕ цепочки каждой из ДНК перемножаются по такому же приницпу, как перемножаются РНК выше. Вторая цепочка результирующей ДНК строится как комплиментарная первой 7. Цепочки РНК и первую и вторую у ДНК можно проверять на равенство 8. Оба класса должны давать осмысленный вывод как при print, так и просто при вызове в ячейке | Обдумайте и создайте необходимые и, возможно, вспомогательные классы, настройте наследование, если требуется. Полученная структура должна быть адекватной и удобной, готовой к простому расширению функционала, если потребуется

Сайт построен с использованием Pelican. За основу оформления взята тема от Smashing Magazine. Исходные тексты программ, приведённые на этом сайте, распространяются под лицензией GPLv3, все остальные материалы сайта распространяются под лицензией CC-BY.

Абстрактные методы в Python

31 августа 2013 г. Archy Просмотров: 41224 RSS 3
ООП на Python » Python для начинающих abstract method python, Абстрактные методы, ооп python

Абстрактные методы в Python

Абстрактные методы содержат только определение метода без реализации. Предполагается, что класс-потомок должен переопределить метод и реализовать его функциональность. Чтобы такое предположение сделать более очевидным, часто внутри абстрактного метода возбуждают исключение.

Абстрактные методы

class Class1(object): def test(self, x): # Абстрактный метод # Возбуждаем исключение с помощью raise raise NotImplementedError("Необходимо переопределить метод") class Class2(Class1): # Наследуем абстрактный метод def test(self, x): # Переопределяем метод print x class Class3(Class1): # Класс не переопределяет метод pass c2 = Class2() c2.test(50) # Выведет: 50 c3 = Class3() try: # Перехватываем исключения c3.test(50) # Ошибка. Метод test() не переопределен except NotImplementedError, msg: print msg # Выведет: Необходимо переопределить метод

Начиная с версии Python 2.6, в состав библиотеки входит модуль abc. В этом модуле определен декоратор @abstractmethod, который позволяет указать, что метод, перед которым расположен декоратор, является абстрактным. При попытке создать экземпляр класса-потомка, в котором не переопределен абстрактный метод, возбуждается исключение TypeErrror. Рассмотрим использование декоратора @abstractmethod на примере.

Использование декоратора @abstractmethod

from abc import ABCMeta, abstractmethod class Class1(object): __metaclass__ = ABCMeta @abstractmethod def test(self, x): # Абстрактный метод pass class Class2(Class1): # Наследуем абстрактный метод def test(self, x): # Переопределяем метод print x class Class3(Class1): # Класс не переопределяет метод pass c2 = Class2() c2.test(50) # Выведет: 50 try: c3 = Class3() # Ошибка. Метод test() не переопределен c3.test(50) except TypeError, msg: print msg # Can't instantiate abstract class Class3 # with abstract methods test

Вам нужен качественный и красивый логотип? Советуем вам заказать дизайн логотипов от студии «designcontest.ru«. Все по самым доступным ценам!

Еще записи по теме

  • Python-рецепты. Словари
  • Основы SQLite — С чего начать?
  • Классы нового стиля. ООП в Python
  • Как выбрать хостинг для сайта без какого-либо риска?
  • Стандартные библиотеки и сторонние библиотеки Python
  • Python работа с FTP — Модуль ftplib
  • Модуль threading на примерах

Абстрактные классы в Python

Абстрактный класс — очень важная концепция объектно-ориентированного программирования. Это хорошая практика принципа «не повторяйся«. В большом проекте дублирование кода примерно равно повторному использованию ошибок, и один разработчик не может запомнить детали всех классов. Поэтому очень полезно использовать абстрактный класс для определения общего интерфейса для различных реализаций.

Абстрактный класс имеет некоторые особенности, а именно:

  • Абстрактный класс не содержит всех реализаций методов, необходимых для полной работы, это означает, что он содержит один или несколько абстрактных методов. Абстрактный метод — это только объявление метода, без его подробной реализации.
  • Абстрактный класс предоставляет интерфейс для подклассов, чтобы избежать дублирования кода. Нет смысла создавать экземпляр абстрактного класса.
  • Производный подкласс должен реализовать абстрактные методы для создания конкретного класса, который соответствует интерфейсу, определенному абстрактным классом. Следовательно, экземпляр не может быть создан, пока не будут переопределены все его абстрактные методы.

Короче говоря, абстрактный класс определяет общий интерфейс для набора подклассов. Он предоставляет общие атрибуты и методы для всех подклассов, чтобы уменьшить дублирование кода. Он также заставляет подклассы реализовывать абстрактные методы, чтобы избежать каких-то несоответствий.

Определение абстрактного класса в Python.

Python поставляется с модулем под названием abc , который предоставляет полезные вещи для абстрактного класса. Абстрактный класс можно определить с помощью класса abc.ABC , а абстрактный метод определить с помощью abc.abstractmethod . ABC — это аббревиатура, сокращение от слов абстрактный базовый класс.

Примечание: Класс не является настоящим абстрактным, если он имеет абстрактные методы, но не наследуется от abc.ABC , это означает, что он может быть создан. Например:

from abc import ABC, abstractmethod class Animal(ABC): @abstractmethod def move(self): pass a = Animal() # TypeError: Can't instantiate abstract class Animal with abstract methods move class Animal(): @abstractmethod def move(self): pass a = Animal() 

Определение абстрактного метода абстрактного класса.

Декоратор @abstractmethod может использоваться для объявления абстрактных методов свойств и дескрипторов требует, чтобы метакласс класса был ABCMeta или производным от него. Абстрактный класс не может быть создан, пока не будут переопределены все его абстрактные методы и свойства.

На самом деле абстрактный метод в Python не обязательно должен быть «полностью абстрактным«, что отличается от некоторых других объектно-ориентированных языков программирования. Можно определить некоторые общие вещи в абстрактном методе и использовать функцию super() для вызова его в подклассах.

from abc import ABC, abstractmethod class Animal(ABC): @abstractmethod def move(self): print('Animal moves') class Cat(Animal): def move(self): super().move() print('Cat moves') c = Cat() c.move() # Animal moves # Cat moves 

Как показано в приведенном выше примере, абстрактный метод .move() может содержать некоторые функции и может вызываться подклассом с помощью super() . Хотя у него небольшая реализация, это все еще абстрактный метод, и пользователю необходимо полностью реализовать его в подклассах.

Совместно с декоратором @abstractmethod можно использовать такие декораторы, как @property , @classmethod и @staticmethod . Когда декоратор @abstractmethod применяется в сочетании с другими дескрипторами методов, его следует применять как самый внутренний декоратор

Определение абстрактного метода класса.
from abc import ABC, abstractmethod class C(ABC): @classmethod @abstractmethod def my_abstract_classmethod(cls, . ): . 
Определение абстрактного статического метода класса.
from abc import ABC, abstractmethod class C(ABC): @staticmethod @abstractmethod def my_abstract_staticmethod(. ): . 
Определение абстрактного дескриптора класса.

В приведенном примере определяется свойство только для чтения:

from abc import ABC, abstractmethod class C(ABC): @property @abstractmethod def my_abstract_property(self): . 

Также можно определить абстрактное свойство для чтения и записи, соответствующим образом пометив один или несколько базовых методов как абстрактные:

from abc import ABC, abstractmethod class C(ABC): @property def x(self): . @x.setter @abstractmethod def x(self, val): . 

Если только некоторые компоненты являются абстрактными, только эти компоненты необходимо обновить, чтобы создать конкретное свойство в подклассе:

class D(C): @C.x.setter def x(self, val): . 

Динамическое добавление абстрактных методов после создания класса.

Динамическое добавление абстрактных методов в класс или попытка изменить статус абстракции метода или класса после его создания поддерживаются только с помощью функции abc.update_abstractmethods() .

abc.update_abstractmethods(cls) :

Новое в версии Python 3.10.

Функция abc.update_abstractmethods(cls) предназначена для пересчета статуса абстракции абстрактного класса. Эту функцию следует вызывать, если абстрактные методы класса были реализованы или изменены после их создания. Обычно эту функцию следует вызывать из декоратора класса.

Возвращает cls , чтобы разрешить использование в качестве декоратора класса.

Если cls не является экземпляром ABC , ничего не делает.

Примечание. Эта функция предполагает, что суперклассы cls уже обновлены. Она не обновляет никаких подклассов.

Общий пример концепции определения абстрактных классов.

from abc import ABC, abstractmethod class C(ABC): @abstractmethod def my_abstract_method(self, . ): . @classmethod @abstractmethod def my_abstract_classmethod(cls, . ): . @staticmethod @abstractmethod def my_abstract_staticmethod(. ): . @property @abstractmethod def my_abstract_property(self): . @my_abstract_property.setter @abstractmethod def my_abstract_property(self, val): . @abstractmethod def _get_x(self): . @abstractmethod def _set_x(self, val): . x = property(_get_x, _set_x) 
  • ОБЗОРНАЯ СТРАНИЦА РАЗДЕЛА
  • Пространство имен и область видимости в классах
  • Определение классов
  • Объект класса и конструктор класса
  • Создание экземпляра класса
  • Метод экземпляра класса
  • Что такое метод класса и зачем нужен
  • Что такое статический метод в классах Python и зачем нужен
  • Атрибуты класса и переменные экземпляра класса
  • Кэширование методов экземпляра декоратором lru_cache
  • Закрытые/приватные методы и переменные класса Python
  • Наследование классов
  • Множественное наследование классов
  • Абстрактные классы
  • Перегрузка методов в классе Python
  • Что такое миксины и как их использовать
  • Класс Python как структура данных, подобная языку C
  • Создание пользовательских типов данных
  • Специальные (магические) методы класса Python
  • Базовая настройка классов Python магическими методами
  • Настройка доступа к атрибутам класса Python
  • Дескриптор класса для чайников
  • Протокол дескриптора класса
  • Практический пример дескриптора
  • Использование метода .__new__() в классах Python
  • Специальный атрибут __slots__ класса Python
  • Специальный метод __init_subclass__ класса Python
  • Определение метаклассов metaclass
  • Эмуляция контейнерных типов в классах Python
  • Другие специальные методы класса
  • Как Python ищет специальные методы в классах
  • Шаблон проектирования Фабрика и его реализация

Зачем нужны абстрактные методы в Python?

В примере у метода помеченного как абстрактный реализовано тело:

@abstractmethod def tell(self): '''Вывести информацию.''' print('Имя:"" Возраст:""'.format(self.name, self.age), end=" ")

Но потом при его реализации мы ему тело получается снова создаем:

def tell(self): SchoolMember.tell(self) print('Оценки: ""'.format(self.marks))

Т.е. по идее строка:

print('Имя:"" Возраст:""'.format(self.name, self.age), end=" ")
  • Вопрос задан более трёх лет назад
  • 3225 просмотров

Комментировать
Решения вопроса 1

gim0

Абстрактные методы, по определению, не имеют реализации. Декоратор @abstractmethod выглядит как какой-то костыль существующий из-за того, что в Python нельзя объявить метод с пустым телом как это происходит в других ЯП, в нём хотя бы pass должен присутствовать. Зачем в этом примере добавили print в абстрактный метод знает только автор этого примера, оно не нужно.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *