Python нативно не поддерживает интерфейсы. Все обсуждения, которые я находил, ссылались на "duck typing". Но, к примеру, если у меня есть набор классов, которые мне при переборе нужно различать по поддерживаемым ими действиям, которые не очень зависят от базового класса, то в случае с интерфейсами я могу проверить, что класс реализует, скажем, интерфейс ILoggable, тогда я буду уверен ,что в классе есть все нужные методы. А вот в случае утиной типизации придётся либо проверять каждый нужный метод, либо делать какую-то обёртку, которая фактически будет делать тоже самое, что и интерфейс. Что на этот счёт говорит идеология питона? Раз интерфейсов нет, значит как-то обходятся без них (сторонние реализации в расчёт не беру).
Abstract base classes complement duck-typing by providing a way to define interfaces when other techniques like hasattr() would be clumsy or subtly wrong (for example with magic methods). ABCs introduce virtual subclasses, which are classes that don’t inherit from a class but are still recognized by isinstance() and issubclass(); see the abc module documentation. Python comes with many built-in ABCs for data structures (in the collections module), numbers (in the numbers module), and streams (in the io module). You can create your own ABCs with the abc module.
Видимо, это то, что надо.
От себя скажу, что не замечаю сильного увлечения ABC в сообществе (и вообще проверкой интерфейсов) — они скорее для стандартной библиотеки.
ABS я видел. Меня больше не техническая сторона, а идеологическая интересует. Пытаюсь понять, как в питоне правильно подобные вещи делать. Ниже vvpoloskin пишет про множественное наследование - вполне вариант.
@Tiendil в том-то и дело, что меня интересует меньшинство случаев )
Пример из жизни, который послужил поводом для размышлений: есть система плагинов. Все плагины хранятся в одном реестре. При возникновении какого-то события, обработчик проходит по списку плагинов и смотрит, у кого есть интерфейс on. Если класс плагина реализует такой интерфейс, значит вызываем соответствующие методы у этого класса
Можно, конечно, проверять наличие методов вместо интерфейса, но проверка интерфейса лаконичнее.
В таком случае проверка наличия метода — это нормальный подход. Duck Typing и всё такое.
Хотя, я бы предложил явную регистрацию «интерфейсных» методов. Не обязательно накладывать на разработчиков плагинов лишние ограничения (в данном случае по именованию). Мало ли что потом изменится.
P.S. Функция getattr имеет возможность возвращать дефолтное значение, если не находит аттрибут. Поэтому можно и так написать: getattr(plugin, 'on', lambda *argv, **kwargs: None)() И никаких проблем с интерфейсами :-)
Ну проект с плагинами не на питоне, там на интерфейсах всё работает.
Спасибо, я раньше с утиной типизацией на практике не сталкивался. Думалось, что проверка наличия метода - это что-то сродни рефлексии и лучше так не делать. Получается, что в случае с питоном это норма.
Почему бы не попробовать интерфейсную часть сделать отдельным классом, запустить его во множественное наследование и проверять его вхождение в bases? Интерфейс у вас будет как миксин.
@diswest Еще вариант пришел в голову - сделайте внутренний класс. То есть у вас будет класс A, а внутри будет что-то поля (список?) Interface, в котором будут классы. Это становится возможным благодаря тому, что в питоне даже класс - это объект)