Preventing a class from direct instantiation in Python

mohi666 picture mohi666 · Nov 3, 2011 · Viewed 16.1k times · Source

I have a super class with a method that calls other methods that are only defined in its sub classes. That's why, when I create an instance of my super class and call its method, it cannot find the method and raises an error.

Here is an example:

class SuperClass(object):

  def method_one(self):
    value = self.subclass_method()
    print value


class SubClassOne(SuperClass):

  def subclass_method(self):
    return 'subclass 1'


class SubClassTwo(SuperClass):

  def subclass_method(self):
    return 'nubclass 2'


s1 = SubClassOne()
s1.method_one()

s2 = SubClassTwo()
s2.method_one()

c = SuperClass()
c.method_one()

# Results:
# subclass 1
# nubclass 2
# Traceback (most recent call last):
#   File "abst.py", line 28, in <module>
#     c.method_one()
#   File "abst.py", line 4, in method_one
#     value = self.subclass_method()
# AttributeError: 'SuperClass' object has no attribute 'subclass_method'

I was thinking about changing the init of super class and verify the type of object, when a new instance is created. If the object belongs to super class raise an error. However, I'm not too sure if it's the Pythonic way of doing it.

Any recommendations?

Answer

kindall picture kindall · Nov 3, 2011

I would override __new__() in the base class and simply fail to instantiate at all if it's the base class.

class BaseClass(object):

    def __new__(cls, *args, **kwargs):
        if cls is BaseClass:
            raise TypeError("base class may not be instantiated")
        return object.__new__(cls, *args, **kwargs)

This separates concerns a little better than having it in __init__(), and "fails fast."