Search code examples
pythonclassooplockingsuperclass

Preventing a class from direct instantiation in Python


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?


Solution

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

    class BaseClass:    # Py3
    
        def __new__(cls, *args, **kwargs):
            if cls is BaseClass:
                raise TypeError(f"only children of '{cls.__name__}' may be instantiated")
            return object.__new__(cls, *args, **kwargs)
    

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