Is it possible to make abstract classes in Python?
Use the abc
module to create abstract classes. Use the abstractmethod
decorator to declare a method abstract, and declare a class abstract using one of three ways, depending upon your Python version.
In Python 3.4 and above, you can inherit from ABC
. In earlier versions of Python, you need to specify your class's metaclass as ABCMeta
. Specifying the metaclass has different syntax in Python 3 and Python 2. The three possibilities are shown below:
# Python 3.4+
from abc import ABC, abstractmethod
class Abstract(ABC):
@abstractmethod
def foo(self):
pass
# Python 3.0+
from abc import ABCMeta, abstractmethod
class Abstract(metaclass=ABCMeta):
@abstractmethod
def foo(self):
pass
# Python 2
from abc import ABCMeta, abstractmethod
class Abstract:
__metaclass__ = ABCMeta
@abstractmethod
def foo(self):
pass
Whichever way you use, you won't be able to instantiate an abstract class that has abstract methods, but will be able to instantiate a subclass that provides concrete definitions of those methods:
>>> Abstract()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class Abstract with abstract methods foo
>>> class StillAbstract(Abstract):
... pass
...
>>> StillAbstract()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class StillAbstract with abstract methods foo
>>> class Concrete(Abstract):
... def foo(self):
... print('Hello, World')
...
>>> Concrete()
<__main__.Concrete object at 0x7fc935d28898>
The old-school (pre-PEP 3119) way to do this is just to raise NotImplementedError
in the abstract class when an abstract method is called.
class Abstract(object):
def foo(self):
raise NotImplementedError('subclasses must override foo()!')
class Derived(Abstract):
def foo(self):
print 'Hooray!'
>>> d = Derived()
>>> d.foo()
Hooray!
>>> a = Abstract()
>>> a.foo()
Traceback (most recent call last): [...]
This doesn't have the same nice properties as using the abc
module does. You can still instantiate the abstract base class itself, and you won't find your mistake until you call the abstract method at runtime.
But if you're dealing with a small set of simple classes, maybe with just a few abstract methods, this approach is a little easier than trying to wade through the abc
documentation.