Skip to content
Advertisement

Python abstract classes – how to discourage instantiation?

I come from a C# background where the language has some built in “protect the developer” features. I understand that Python takes the “we’re all adults here” approach and puts responsibility on the developer to code thoughtfully and carefully.

That said, Python suggests conventions like a leading underscore for private instance variables. My question is, is there a particular convention for marking a class as abstract other than just specifying it in the docstrings? I haven’t seen anything in particular in the python style guide that mentions naming conventions for abstract classes.

I can think of 3 options so far but I’m not sure if they’re good ideas:

  1. Specify it in the docstring above the class (might be overlooked)
  2. Use a leading underscore in the class name (not sure if this is universally understood)
  3. Create a def __init__(self): method on the abstract class that raises an error (not sure if this negatively impacts inheritance, like if you want to call a base constructor)

Is one of these a good option or is there a better one? I just want to make sure that other developers know that it is abstract and so if they try to instantiate it they should accept responsibility for any strange behavior.

Advertisement

Answer

If you’re using Python 2.6 or higher, you can use the Abstract Base Class module from the standard library if you want to enforce abstractness. Here’s an example:

from abc import ABCMeta, abstractmethod

class SomeAbstractClass(object):
    __metaclass__ = ABCMeta

    @abstractmethod
    def this_method_must_be_overridden(self):
        return "But it can have an implementation (callable via super)."

class ConcreteSubclass(SomeAbstractClass):
    def this_method_must_be_overridden(self):
        s = super(ConcreteSubclass, self).this_method_must_be_overridden()
        return s.replace("can", "does").replace(" (callable via super)", "")

Output:

>>> a = SomeAbstractClass()
Traceback (most recent call last):
  File "<pyshell#13>", line 1, in <module>
    a = SomeAbstractClass()
TypeError: Can't instantiate abstract class SomeAbstractClass with abstract
methods this_method_must_be_overridden
>>> c = ConcreteSubclass()
>>> c.this_method_must_be_overridden()
'But it does have an implementation.'
User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement