Когда использовать 'raise NotImplementedError'?
Следует ли помнить себя и свою команду, чтобы правильно реализовать класс?
Я не полностью использую абстрактный класс следующим образом:
class RectangularRoom(object):
def __init__(self, width, height):
raise NotImplementedError
def cleanTileAtPosition(self, pos):
raise NotImplementedError
def isTileCleaned(self, m, n):
raise NotImplementedError
Ответы
Ответ 1
Как говорится в документации [docs],
В пользовательских базовых классах абстрактные методы должны вызывать это исключение, когда им требуется, чтобы производные классы переопределяли метод, или пока класс разрабатывается, чтобы указать, что реальная реализация еще должна быть добавлена.
Обратите внимание, что хотя основной заявленный вариант использования этой ошибки является признаком абстрактных методов, которые должны быть реализованы на унаследованных классах, вы можете использовать его так или иначе, как для указания маркера TODO
.
Ответ 2
Как Уриэль говорит, он предназначен для метода в абстрактном классе, который должен быть реализован в дочернем классе, но может использоваться для обозначения TODO.
Python 3 поставляется с альтернативой для первого варианта использования: Абстрактные базовые классы. Это помогает создавать абстрактные классы:
class C(abc.ABC):
@abstractmethod
def my_abstract_method(self, ...):
...
При создании экземпляра C
вы получите сообщение об ошибке, потому что my_abstract_method
является абстрактным. Вам нужно реализовать его в дочернем классе.
TypeError: Can't instantiate abstract class C with abstract methods my_abstract_method
Подкласс C
и реализовать my_abstract_method
.
class D(C):
def my_abstract_method(self, ...):
...
Теперь вы можете создать экземпляр D
.
C.my_abstract_method
не должно быть пустым. Его можно вызвать из D
с помощью super()
.
Преимущество этого над NotImplementedError
заключается в том, что вы получаете явное Exception
во время создания, а не во время вызова метода.
Ответ 3
Возможно, вы захотите использовать декоратор @property
,
>>> class Foo():
... @property
... def todo(self):
... raise NotImplementedError("To be implemented")
...
>>> f = Foo()
>>> f.todo
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in todo
NotImplementedError: To be implemented
Ответ 4
Рассмотрим, если бы это было:
class RectangularRoom(object):
def __init__(self, width, height):
pass
def cleanTileAtPosition(self, pos):
pass
def isTileCleaned(self, m, n):
pass
и вы подклассом и забудьте сообщить ему, как isTileCleaned()
или, возможно, более вероятно, оставьте его как isTileCleaned()
. Затем в вашем коде вы получите None
, когда вы его вызовете.
- Вы получите переопределенную функцию, которую хотите? Определенно нет.
- Является ли
None
допустимым выходом? Кто знает.
- Это намеренное поведение? Почти наверняка нет.
- Вы получите сообщение об ошибке? Это зависит.
Это заставляет вас реализовать его, поскольку будет выдавать исключение, пока вы это сделаете. Это устраняет много бесшумных ошибок. Это похоже на то, почему голый, но почти никогда не является хорошей идеей: потому что люди делают ошибки, и это гарантирует, что они не будут охвачены под ковриком.