Абстрактные методы в Python
Мне нужно что-то вроде метода abstract protected
в Python (3.2):
class Abstract:
def use_concrete_implementation(self):
print(self._concrete_method())
def _concrete_method(self):
raise NotImplementedError()
class Concrete(Abstract):
def _concrete_method(self):
return 2 * 3
Действительно ли полезно определить "абстрактный" метод только для того, чтобы поднять NotImplementedError?
Хорошо ли использовать символ подчеркивания для абстрактных методов, который был бы protected
на других языках?
Улучшен ли какой-нибудь абстрактный базовый класс (abc)?
Ответы
Ответ 1
В Python вы обычно избегаете использования таких абстрактных методов. Вы определяете интерфейс по документации и просто предполагаете, что объекты, переданные в этом интерфейсе ( "утиная печать" ).
Если вы действительно хотите определить абстрактный базовый класс с абстрактными методами, это можно сделать с помощью модуля abc
:
from abc import ABCMeta, abstractmethod
class Abstract(metaclass=ABCMeta):
def use_concrete_implementation(self):
print(self._concrete_method())
@abstractmethod
def _concrete_method(self):
pass
class Concrete(Abstract):
def _concrete_method(self):
return 2 * 3
Опять же, это не обычный способ Python делать что-то. Одна из основных целей модуля abc
заключалась в том, чтобы ввести механизм перегрузки isinstance()
, но isinstance()
проверки обычно избегают в пользу утиного ввода. Используйте его, если вам это нужно, но не как общий шаблон для определения интерфейсов.
Ответ 2
Если вы сомневаетесь, делать то, что делает Гвидо.
Нет подчеркивания. Просто определите "абстрактный метод" как однострочный, который вызывает NotImplementedError:
class Abstract():
def ConcreteMethod(self):
raise NotImplementedError("error message")
Ответ 3
В принципе, пустой метод в базовом классе здесь не нужен. Просто сделайте это так:
class Abstract:
def use_concrete_implementation(self):
print(self._concrete_method())
class Concrete(Abstract):
def _concrete_method(self):
return 2 * 3
На самом деле вам обычно не нужен базовый класс в Python. Поскольку все вызовы разрешены динамически, если этот метод присутствует, он будет вызываться, если нет, будет увеличен AttributeError
.
Внимание: В документации необходимо указать, что _concrete_method
должен быть реализован в подклассах.