Должен ли я использовать абстрактные методы в этом сценарии Python?

1

Я не уверен, что мой подход - хороший дизайн, и я надеюсь, что смогу получить совет. Я думаю где-то вдоль линии абстрактного метода, но в этом случае я хочу, чтобы этот метод был необязательным. Вот как я это делаю сейчас...

from pymel.core import *

class A(object):
    def __init__(self, *args, **kwargs):
        if callable(self.createDrivers):
            self._drivers = self.createDrivers(*args, **kwargs)
            select(self._drivers)

class B(A):
    def createDrivers(self, *args, **kwargs):
        c1 = circle(sweep=270)[0]
        c2 = circle(sweep=180)[0]
        return c1, c2

b = B()

В приведенном выше примере я просто создаю две дуги окружности в PyMEL для Maya, но я полностью намерен создавать дополнительные подклассы, которые могут иметь или не иметь метод createDrivers вообще! Поэтому я хочу, чтобы это было необязательным, и мне интересно, мой подход - это хорошо, если бы мой подход мог быть улучшен?

  • 0
    Извините, но недостаточно информации, чтобы прокомментировать дизайн. Из примера я не вижу никакой причины использовать A и почему B - это A. Как форма, я думаю, что вы слишком обдумываете это;)
  • 1
    Не import * .
Показать ещё 6 комментариев
Теги:
optional
subclass
pymel
abstract-methods

3 ответа

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

У вас все еще есть проблема, когда вы наследуете свой класс B, и это вызовет A.__init__, и если вы не реализуете createDrivers в подклассе, эта строка callable(self.createDrivers) будет вызывать ошибку как таковой createDrivers не существует (AttributeError), я думаю, если бы я был вами, я сделаю это так:

class A(object):
    def __init__(self, *args, **kwargs):
       try:
           self._drivers = self.createDrivers(*args, **kwargs)
           select(self._drivers)
       except NotImplementedError:
           pass

    def createDrivers(self, *args, **kwargs):
        raise NotImplementedError("This class wasn't implemented")

class B(A):
    def createDrivers(self, *args, **kwargs):
        c1 = circle(sweep=270)[0]
        c2 = circle(sweep=180)[0]
        return c1, c2

class C(A):
    pass

Другой способ - заменить callable(self.createDrivers) на hasattr(self, 'createDrivers').

  • 0
    Я могу видеть, как эта тема будет весьма спорной. Все приводят примеры этой работы, но никто из них не дает мне теплых размышлений. Я не могу решить, какой подход лучше. У всех есть свои плюсы и минусы. Это связано с тем, что он выглядит как абстрактный метод, хотя на самом деле его намерение не является обязательным.
  • 1
    @sfjedi: у этого метода есть преимущество в том, что он не очень громкий, чего нет у других методов, и я думаю, что это очень важно при реализации API или других, потому что, скажем, кто-то создаст C c = C() как в моем примере, когда он вызывает c.createDrivers это завершится ошибкой, так как createDrivers не реализован, что не похоже на AttributeError, потому что эта ошибка говорит о том, что используется неправильно, с другой стороны, другие методы не делают этого, если кто-то вызывает c.createDrivers ничего не случится! просто тихая ошибка, метод просто существует и ничего не делает !! ??
Показать ещё 8 комментариев
1

Я бы сделал это:

class A(object):
    def __init__(self, *args, **kwargs):
        self.createDrivers(*args, **kwargs)

    def createDrivers(self, *args, **kwargs):
        "Override"
        pass

class B(A):
    def createDrivers(self, *args, **kwargs):
        self._drivers = blabla
  • 0
    Мне очень нравится удобочитаемость вашего решения здесь, но, честно говоря, @Lennart Regebro выше, его решение было почти таким же, и он опубликовал его первым, так что я боюсь, что решение пойдет ему; хотя, я буду голосовать за тебя
  • 0
    Я не хочу спорить о некоторых точках переполнения стека, но я думаю, что отправил за минуту до Леннарта;). Спасибо за отзыв, тем не менее.
Показать ещё 4 комментария
1

Если вы хотите, чтобы createDrivers был необязательным, но все еще всегда там, лучшее не является абстрактным методом, но реализует его в базовом классе как noop.

class A(object):
    def __init__(self, *args, **kwargs):
        self._drivers = self.createDrivers(*args, **kwargs)
        select(self._drivers)

    def createDrivers(self, *args, **kwargs):
        """This should be overridden by subclasses if they need custom drivers"""
        pass
  • 0
    но тогда if callable строка if callable всегда будет оцениваться как true, нет?
  • 0
    Да, но вы можете удалить это if и добавить if self._drivers: или подобное после вызова self.createDrivers .
Показать ещё 2 комментария

Ещё вопросы

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