Есть немного истории за интерфейсами в Python.Исходная позиция, которая господствовала в течение многих лет, заключается в том, что они вам не нужны: Python работает по принципу EAFP (проще просить прощения, чем разрешения).То есть вместо того, чтобы указывать, что вы принимаете, я не знаю, ICloseable объект, вы просто пытаетесь close
объект, когда вам нужно, и если он вызывает исключение, то он вызывает исключение.
Такв этом менталитете вы просто пишете свои классы отдельно и используете их по своему усмотрению.Если один из них не соответствует требованиям, ваша программа выдаст исключение;и наоборот, если вы напишите другой класс с правильными методами, он просто будет работать, без необходимости указывать, что он реализует ваш конкретный интерфейс.
Это работает довольно хорошо, но есть определенные сценарии использования для интерфейсов, особеннос большими проектами программного обеспечения.Окончательное решение в Python состояло в том, чтобы предоставить модуль abc
, который позволит вам написать абстрактные базовые классы , то есть классы, которые вы не можете создать, если не переопределите все их методы.Это ваше решение относительно того, считаете ли вы, что их использование того стоит.
PEP, представляющий азбуку , объясняет гораздо лучше, чем я могу:
В областиВ объектно-ориентированном программировании шаблоны использования для взаимодействия с объектом можно разделить на две основные категории: «вызов» и «проверка».
Вызов означает взаимодействие с объектом путем вызова его методов.Обычно это сочетается с полиморфизмом, поэтому при вызове данного метода может выполняться другой код в зависимости от типа объекта.
Проверка означает способность внешнего кода (вне методов объекта) проверять тип илисвойства этого объекта, и принимать решения о том, как обрабатывать этот объект на основе этой информации.
Оба шаблона использования служат одной и той же общей цели, которая должна поддерживать обработку разнообразных и потенциально новых объектов вединообразным способом, но в то же время позволяя обрабатывать решения по обработке для каждого отдельного типа объекта.
В классической теории ООП вызов является предпочтительным шаблоном использования, и проверка активно не поощряется, считаясь реликвиейболее раннего, процедурного стиля программирования.Однако на практике это представление просто слишком догматично и негибко и приводит к некоторой жесткости дизайна, которая очень сильно расходится с динамической природой такого языка, как Python.
В частности, часто существуетнеобходимо обрабатывать объекты так, как этого не ожидал создатель класса объектов.Это не всегда лучшее решение для встраивания в каждый объект методов, которые удовлетворяют потребности каждого возможного пользователя этого объекта.Более того, существует много мощных философий диспетчеризации, которые находятся в прямом противоречии с классическим требованием ООП о поведении строго инкапсулированного в объекте, например, логикой, управляемой правилом или сопоставлением с шаблоном.Критика проверки со стороны классических теоретиков ООП заключается в отсутствии формализма и особого характера проверяемого.В таком языке, как Python, в котором практически любой аспект объекта может быть отражен и напрямую доступен для внешнего кода, существует множество различных способов проверить, соответствует ли объект определенному протоколу или нет.Например, если спрашивать «Является ли этот объект контейнером изменяемой последовательности?», Можно искать базовый класс «list» или метод « getitem ».Но обратите внимание, что хотя эти тесты могут показаться очевидными, ни один из них не является правильным, так как один генерирует ложные отрицания, а другие ложные положительные.
Общепринятым решением является стандартизация тестов и группировка их вформальная договоренность.Это легче всего сделатьассоциирование с каждым классом набора стандартных тестируемых свойств либо с помощью механизма наследования, либо с помощью других средств.Каждый тест несет с собой набор обещаний: он содержит обещание об общем поведении класса и обещание относительно того, какие другие методы класса будут доступны.
В этом PEP предлагается конкретная стратегия организации этихтесты, известные как абстрактные базовые классы, или ABC.ABC - это просто классы Python, которые добавляются в дерево наследования объекта, чтобы сообщать об определенных функциях этого объекта внешнему инспектору.Тесты выполняются с использованием isinstance (), и наличие определенного ABC означает, что тест пройден.
Кроме того, ABC определяют минимальный набор методов, которые устанавливают характерное поведение типа.Код, который различает объекты на основе их типа ABC, может полагать, что эти методы всегда будут присутствовать.Каждый из этих методов сопровождается обобщенным абстрактным семантическим определением, которое описано в документации для ABC.Эти стандартные семантические определения не применяются, но настоятельно рекомендуется.
Как и все другие вещи в Python, эти обещания имеют характер джентльменского соглашения, что в данном случае означает, что в то время как язык действительно применяет некоторые изОбещания, сделанные в ABC, должны быть реализованы конкретным классом, чтобы обеспечить сохранение оставшихся.