As the documentation states [docs],
In user defined base classes, abstract methods should raise this exception when they require derived classes to override the method, or while the class is being developed to indicate that the real implementation still needs to be added.
Note that although the main stated use case this error is the indication of abstract methods that should be implemented on inherited classes, you can use it anyhow you'd like, like for indication of a TODO marker.
As the documentation states [docs],
In user defined base classes, abstract methods should raise this exception when they require derived classes to override the method, or while the class is being developed to indicate that the real implementation still needs to be added.
Note that although the main stated use case this error is the indication of abstract methods that should be implemented on inherited classes, you can use it anyhow you'd like, like for indication of a TODO marker.
As Uriel says, it is meant for a method in an abstract class that should be implemented in child class, but can be used to indicate a TODO as well.
There is an alternative for the first use case: Abstract Base Classes. Those help creating abstract classes.
Here's a Python 3 example:
class C(abc.ABC):
@abc.abstractmethod
def my_abstract_method(self, ...):
...
When instantiating C, you'll get an error because my_abstract_method is abstract. You need to implement it in a child class.
TypeError: Can't instantiate abstract class C with abstract methods my_abstract_method
Subclass C and implement my_abstract_method.
class D(C):
def my_abstract_method(self, ...):
...
Now you can instantiate D.
C.my_abstract_method does not have to be empty. It can be called from D using super().
An advantage of this over NotImplementedError is that you get an explicit Exception at instantiation time, not at method call time.
When I run the following code it it reports TypeError: Can't instantiate abstract class Dog with abstract method speak:
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def speak(self):
raise NotImplementedError
class Dog(Animal):
def walk(self):
print('dog walks instead of speaks')
dog = Dog()I understand exactly why - I haven't provided an implementation of speak() within Dog, but I thought that was the whole point of the raise NotImplementedError line? So what actually would trigger the NotImplementedError?
You should use an abstract class because it is the appropriate choice for your model, not because of some desired side effect. So instead of thinking benefits, think meaning.
An abstract class classifies classes and allows you to group common data and behavior for that group of classes. If that fits your problem domain (you recognize multiple classes with common properties), use an abstract class. If it does not and you just want to hint an implementor to complete an implementation, create a template or something and throw your exceptions.
Not being able to create an instance of an abstract class is not a "drawback" of the thing, it is inherent to its purpose.
"Abstract class" is a general programming concept. An abstract class as a programming concept is a class that should never be instantiated at all but should only be used as a base class of another class.
In some languages you can explicitly specifiy that a class should be abstract. For example, in C++ any class with a virtual method marked as having no implementation. In some languages, there is no such thing.
If your language allows it, write abstract classes in a way that explicitely marks them as abstract. If not, either use some other means that let you detect instantiation of an abstract class, or just ignore the problem because using an instance of an abstract class will not likely produce any usable result.
It's worth noting that, while the Python documentation provides a use case (and probably the canonical one) for this exception, it doesn't specifically exclude its use in other scenarios.
I would consider it appropriate to raise a NotImplementedError exception if you haven't overridden a method in a base class yet (to satisfy the "interface").
A cursory check on Google suggests that people will understand what you mean if you use the exception in this fashion. There are no side effects or unintended consequences that I know of; the method will simply throw an exception if it is called, and it will throw an exception that is well-understood by everyone.
The documentation for Python 3 reflects this exact usage:
In user defined base classes, abstract methods should raise this exception when they require derived classes to override the method, or while the class is being developed to indicate that the real implementation still needs to be added. [Emphasis added]
This will be understood, whether you do it or not should depend on local (team or company) conventions. Note that it makes less sense in the context of TDD as the TEST should be what determines that the method isn't implemented.
The short version is: use if you and your team consider it appropriate.
Yes, you can. Use the @property decorator. For instance, if you have a field called "example" then can't you do something like this:
class Base(object):
@property
def example(self):
raise NotImplementedError("Subclasses should implement this!")
Running the following produces a NotImplementedError just like you want.
b = Base()
print b.example
Alternate answer:
@property
def NotImplementedField(self):
raise NotImplementedError
class a(object):
x = NotImplementedField
class b(a):
# x = 5
pass
b().x
a().x
This is like Evan's, but concise and cheap--you'll only get a single instance of NotImplementedField.
Before abc was introduced you would see this frequently.
class Base(object):
def go(self):
raise NotImplementedError("Please Implement this method")
class Specialized(Base):
def go(self):
print "Consider me implemented"
Something along these lines, using ABC
import abc
class Shape(object):
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def method_to_implement(self, input):
"""Method documentation"""
return
Also read this good tutorial: https://pymotw.com/3/abc/
You can also check out zope.interface which was used prior to introduction of ABC in python.
- http://pypi.python.org/pypi/zope.interface
- https://zopeinterface.readthedocs.io/en/latest/README.html