Общепринято ли вызывать NotImplementedError для методов, реализация которых находится на рассмотрении, но не планируется абстрагироваться?

34

Мне нравится поднимать NotImplementedErrorдля любого метода, который я хочу реализовать, но там, где я еще не удосужился сделать это. Возможно, у меня уже есть частичная реализация, но добавьте ее, raise NotImplementedError()потому что она мне пока не нравится. С другой стороны, мне также нравится придерживаться соглашений, потому что это облегчит другим людям поддержку моего кода, и соглашения могут существовать по уважительной причине.

Однако документация Pythons для NotImplementedError гласит:

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

Это гораздо более конкретный, формальный вариант использования, чем тот, который я описал. Это хороший, традиционный стиль, чтобы NotImplementedErrorпросто указать, что эта часть API находится в стадии разработки? Если нет, есть ли другой стандартизированный способ указания этого?

Геррит
источник
Что вы подразумеваете под "подходящим"?
Роберт Харви
1
@RobertHarvey Я полагаю, я имею в виду обычный, после общего использования. Я перефразировал мой вопрос сейчас.
Gerrit
1
Здесь мы в основном используем C #, но такого рода выдача исключений здесь идиоматична, и я ожидаю, что это произойдет в другом месте. Перерыв рано и громкий перерыв - это хорошее руководство для быстрого выявления потенциальных проблем (читай: недорого).
Теластин
Обычно, если я создаю класс, я просто помещаю комментарии TODO в нереализованные методы, пока не дошел до реализации функциональности. Если бы класс собирался выпустить в производство до того, как это произошло, я бы подумал об исключении.
5
Это то, что Microsoft Visual Studio делает по умолчанию, когда вы используете IDE для «реализации интерфейса». По словам Роберта Харви, результат хорошо понятен.
catfood

Ответы:

34

Стоит отметить, что, хотя документация Python предоставляет вариант использования (и, возможно, канонический) для этого исключения, это не исключает его использования в других сценариях.

Я считаю целесообразным вызвать исключение NotImplementedError, если вы еще не переопределили метод в базовом классе (для удовлетворения «интерфейса»).

Краткая проверка в Google показывает, что люди поймут, что вы имеете в виду, если вы будете использовать исключение таким образом. Там нет никаких побочных эффектов или непреднамеренных последствий, о которых я знаю; метод просто сгенерирует исключение, если он вызывается, и сгенерирует исключение, которое всем хорошо понятно.


Документация для Python 3 отражает это точное использование:

В определяемых пользователем базовых классах абстрактные методы должны вызывать это исключение, когда они требуют, чтобы производные классы переопределяли метод, или когда класс разрабатывается, чтобы указать, что реальная реализация все еще должна быть добавлена . [Акцент добавлен]

Роберт Харви
источник
+1, но я бы также добавил, что для такого рода соглашений небольшая документация может иметь большое значение. Как примечание в одну строку в вики разработчика, readme или руководство по стилю - что-то в этом роде - объясняющее, для чего вы используете это исключение.
Бен Ли
8

Это будет понятно, независимо от того, будете ли вы это делать или нет, должно зависеть от местных соглашений (команды или компании). Обратите внимание, что это имеет меньше смысла в контексте TDD, поскольку TEST должен определять, что метод не реализован.

Краткая версия: используйте, если вы и ваша команда считаете это целесообразным.

jmoreno
источник
5
FWIW, Бросок исключения должен быть хорошим способом заставить тест провалиться, если по какой-то причине вам нужно форсировать это поведение. (Это было бы полезно, например, как часть заглушки для определения метода).
DougM
1

Кажется, что NotImplementedErrorэто обычно поднимается для разработки функций самого Python, например:

@classmethod
def fromkeys(cls, iterable, v=None):
    # There is no equivalent method for counters because setting v=1
    # means that no element can have a count greater than one.
    raise NotImplementedError(
        'Counter.fromkeys() is undefined.  Use Counter(iterable) instead.')

Documetation

fromkeys (итерация)

Этот метод класса не реализован для объектов Counter.

Источник

Collections.Counter.fromkeys

Эмма
источник