Чи умовно підняти NotImplementedError для методів, реалізація яких триває, але не планується бути абстрактним?


34

Мені подобається підняти NotImplementedErrorбудь-який метод, який я хочу впровадити, але де я ще не надумав це зробити. Можливо, я вже маю часткову реалізацію, але передбачте її, raise NotImplementedError()бо мені це ще не подобається. З іншого боку, я також люблю дотримуватися конвенцій, тому що це полегшить іншим людям збереження мого коду, і конвенції можуть існувати з поважної причини.

Однак документація Pythons для NotImplementedError говорить:

Цей виняток походить від RuntimeError. У визначених користувачем базових класах абстрактні методи повинні підвищувати це виняток, коли вони вимагають, щоб похідні класи перекривали метод.

Це набагато конкретніший формальний випадок використання, ніж той, який я описую. Чи є гарним, звичайним стилем підняти NotImplementedErrorпросто, щоб вказати, що ця частина API є незавершеною роботою? Якщо ні, чи існує інший стандартизований спосіб вказівки на це?


Що ви маєте на увазі під "відповідним"?
Роберт Харві

1
@RobertHarvey Я припускаю, що я маю на увазі звичайне, після загального використання. Я перефразував своє запитання зараз.
gerrit

1
Тут ми в основному використовуємо C #, але такий викид винятків тут ідіоматичний, і я б очікував в іншому місці. Перерватися рано та голосно перерватися - хороший настанов для швидкого визначення потенційних проблем (читайте: недорого).
Теластин

Як правило, якщо я створюю клас, я просто розміщую коментарі TODO у нереалізованих методах, поки я не обійдуся реалізацією функціоналу. Якщо клас збирався бути відпущений у виробництво до того, як це сталося, я б розглядав можливість виключення.

5
Для чого це варто, це те, що Microsoft Visual Studio робить за замовчуванням, коли ви використовуєте IDE для "реалізації інтерфейсу". Як каже Роберт Харві, результат добре зрозумілий.
котяча їжа

Відповіді:


34

Варто зазначити, що, хоча документація Python надає випадок використання (і, мабуть, канонічний) для цього винятку, це не виключає конкретно його використання в інших сценаріях.

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

Побіжна перевірка в Google свідчить про те, що люди зрозуміють, що ви маєте на увазі, якщо ви використовуєте виняток таким чином. Я не знаю жодних побічних ефектів чи ненавмисних наслідків; метод просто кине виняток, якщо його викликають, і він викине виняток, який добре розуміють усі.


Документація для Python 3 відображає це точне використання:

У визначених користувачем базових класах абстрактні методи повинні підвищувати це виняток, коли вони вимагають, щоб похідні класи перекривали метод або коли клас розробляється, щоб вказати на те, що реальна реалізація все-таки повинна бути додана . [Наголос додано]


+1, але я також додам, що для такого роду конвенцій невелика документація може пройти довгий шлях. Як примітка про однорядку у вікі для розробників, репо readme або вказівки щодо стилів - щось подібне - пояснення для чого ви використовуєте цей виняток.
Бен Лі

8

Це буде зрозуміло, чи будете ви це робити чи ні, має залежати від місцевих (команда чи компанія) конвенцій. Зауважте, що в контексті TDD має менше сенсу, оскільки тест повинен визначати те, що метод не буде реалізований.

Коротка версія: використовуйте, якщо ви та ваша команда вважаєте це доречним.


5
FWIW, Метання винятків повинно бути хорошим способом не допустити тесту, якщо з якихось причин вам потрібно змусити цю поведінку. (Це було б корисно, наприклад, як частина визначення методу intellisense stub.)
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.')

Документація

від ключів (ітерабельно)

Цей метод класу не реалізований для об'єктів Counter.

Джерело

Collections.Counter.fromkeys

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.