Скажем, я создаю класс с именем Bird, который я хочу использовать только как родительский класс, и производные классы, как ожидается, будут иметь метод flap_wings
:
class Bird:
def fly(self):
self.flap_wings()
Ожидаемый производный класс может выглядеть так:
class Eagle(Bird):
def flap_wings(self):
print('flapping wings')
Какой хороший, понятный способ для Bird
утверждать, что его производные классы имеют метод flap_wings
а также содержат документацию о том, что flap_wings
?
Прямо сейчас я использую __init_subclass__
:
class Bird:
def fly(self):
self.flap_wings()
def __init_subclass__(cls, **kwargs):
assert hasattr(cls, 'flap_wings'), (
"Derived classes have to have a flap_wings method which should "
"print 'flapping wings'."
)
Но выражение assert появляется только после создания класса Bird и не является "реальной" docstring, к которой можно получить доступ с помощью help
.
Я знаю, что это открытый вопрос, но какие другие способы лучше? Это не противоречит правилам определения flap_wings
в Bird
первых, может быть, просто с телом pass
и строку документации. Но я просто не мог найти "стандартные" способы справиться с этой ситуацией. Поэтому я ищу любые предложения.
Вы можете использовать библиотеку abc
для абстрактных методов:
from abc import ABCMeta, abstractmethod
import six
class Bird(six.with_metaclass(ABCMeta)):
def fly(self):
"""Take flight.
Notes
-----
This depends on the abstract method 'flap_wings'. If you've
not implemented this at the subclass level, your subclass
cannot be properly instantiated.
"""
self.flap_wings()
@abstractmethod
def flap_wings(self):
"""Subclasses must implement this"""
Это устанавливает договор. Любой подкласс, который НЕ реализует метод flap_wings
, вызовет ошибку при создании экземпляра:
class Flamingo(Bird):
pass
>>> Flamingo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class Flamingo with abstract methods flap_wings
В то время как подкласс, реализующий абстрактный метод, будет работать нормально:
class BlueJay(Bird):
def flap_wings(self):
print("Flappity flap")
>>> BlueJay().fly()
Flappity flap
Что касается документирования подкласса, поскольку все подклассы наследуют метод fly
, вы можете включить в его docstring, что он вызывает метод flap_wings
и ожидает, что он будет присутствовать.