Утверждение и документация в классе для методов, которые ожидаются в производных классах

1

Скажем, я создаю класс с именем 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 и строку документации. Но я просто не мог найти "стандартные" способы справиться с этой ситуацией. Поэтому я ищу любые предложения.

Теги:
inheritance
python-3.6
docstring
assertions

1 ответ

2
Лучший ответ

Вы можете использовать библиотеку 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 и ожидает, что он будет присутствовать.

  • 1
    Спасибо за это, особенно показывая организацию строк документации. И хороший выбор птиц. Я буду использовать метаклассы.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню