Equivalent of NotImplementedError for fields in Python

PythonAbstract Class

Python Problem Overview

In Python 2.x when you want to mark a method as abstract, you can define it like so:

class Base:
    def foo(self):
        raise NotImplementedError("Subclasses should implement this!")

Then if you forget to override it, you get a nice reminder exception. Is there an equivalent way to mark a field as abstract? Or is stating it in the class docstring all you can do?

At first I thought I could set the field to NotImplemented, but when I looked up what it's actually for (rich comparisons) it seemed abusive.

Python Solutions

Solution 1 - Python

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):

    def example(self):
        raise NotImplementedError("Subclasses should implement this!")

Running the following produces a NotImplementedError just like you want.

b = Base()
print b.example

Solution 2 - Python

Alternate answer:

def NotImplementedField(self):
    raise NotImplementedError

class a(object):
    x = NotImplementedField

class b(a):
    # x = 5


This is like Evan's, but concise and cheap--you'll only get a single instance of NotImplementedField.

Solution 3 - Python

A better way to do this is using Abstract Base Classes:

import abc

class Foo(abc.ABC):

    def demo_attribute(self):
        raise NotImplementedError

    def demo_method(self):
        raise NotImplementedError

class BadBar(Foo):

class GoodBar(Foo):
    demo_attribute = 'yes'

    def demo_method(self):
        return self.demo_attribute

bad_bar = BadBar()
# TypeError: Can't instantiate abstract class BadBar \
# with abstract methods demo_attribute, demo_method

good_bar = GoodBar()
# OK

Note that you should still have raise NotImplementedError instead of something like pass, because there is nothing preventing the inheriting class from calling super().demo_method(), and if the abstract demo_method is just pass, this will fail silently.

Solution 4 - Python

def require_abstract_fields(obj, cls):
    abstract_fields = getattr(cls, "abstract_fields", None)
    if abstract_fields is None:

    for field in abstract_fields:
        if not hasattr(obj, field):
            raise RuntimeError, "object %s failed to define %s" % (obj, field)

class a(object):
    abstract_fields = ("x", )
    def __init__(self):
        require_abstract_fields(self, a)

class b(a):
    abstract_fields = ("y", )
    x = 5
    def __init__(self):
        require_abstract_fields(self, b)
        super(b, self).__init__()


Note the passing of the class type into require_abstract_fields, so if multiple inherited classes use this, they don't all validate the most-derived-class's fields. You might be able to automate this with a metaclass, but I didn't dig into that. Defining a field to None is accepted.

Solution 5 - Python

It seem that this question was open to both instance attributes and class attributes, I'll focus on the first topic only.

So, for instance attributes, an alternate answer to Evan's is to define a mandatory field using pyfields:

from pyfields import field

class Base(object):
    example = field(doc="This should contain an example.")

b = Base()


   Mandatory field 'example' has not been initialized yet 
   on instance <__main__.Base object at 0x000002C1000C0C18>.

Granted, it does not provide you with the ability to edit the error message by talking about subclasses. But in a way it is more realistic to not talk about subclasses - indeed in python, attributes can be overridden on instances of the base class - not only in subclasses.

Note: I'm the author of pyfields. See documentation for details.

Solution 6 - Python

Here is a simple example how to set required properties/methods for sublasses in Python 3.

class Base:
    requires = ('foo', 'bar')

    def __init_subclass__(cls, **kwargs):
        for requirement in cls.requires:
            if not hasattr(cls, requirement):
                raise NotImplementedError(
                        f'"{cls.__name__}" must have "{requirement}".')

Solution 7 - Python

And here is my solution:

def not_implemented_method(func):
    from functools import wraps
    from inspect import getargspec, formatargspec

    def wrapper(self, *args, **kwargs):
        c = self.__class__.__name__
        m = func.__name__
        a = formatargspec(*getargspec(func))
        raise NotImplementedError('\'%s\' object does not implement the method \'%s%s\'' % (c, m, a))

    return wrapper

def not_implemented_property(func):
    from functools import wraps
    from inspect import getargspec, formatargspec

    def wrapper(self, *args, **kwargs):
        c = self.__class__.__name__
        m = func.__name__
        raise NotImplementedError('\'%s\' object does not implement the property \'%s\'' % (c, m))

    return property(wrapper, wrapper, wrapper)

It can be used as

class AbstractBase(object):
    def test(self):

    def value(self):

class Implementation(AbstractBase):
    value = None

    def __init__(self):
        self.value = 42

    def test(self):
        return True

Solution 8 - Python

An interesting pattern to handle this is to set attribute to None in the parent class and to access the attribute with a function that ensure it has been set in the child class.

Here is an example from django-rest-framework:

class GenericAPIView(views.APIView):


    serializer_class = None


    def get_serializer_class(self):
        assert self.serializer_class is not None, (
            "'%s' should either include a `serializer_class` attribute, "
            "or override the `get_serializer_class()` method."
            % self.__class__.__name__

        return self.serializer_class


All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKivView Question on Stackoverflow
Solution 1 - PythonEvan FosmarkView Answer on Stackoverflow
Solution 2 - PythonGlenn MaynardView Answer on Stackoverflow
Solution 3 - PythonostrokachView Answer on Stackoverflow
Solution 4 - PythonGlenn MaynardView Answer on Stackoverflow
Solution 5 - PythonsmarieView Answer on Stackoverflow
Solution 6 - PythonMark MishynView Answer on Stackoverflow
Solution 7 - PythonfwyzardView Answer on Stackoverflow
Solution 8 - PythonmoppagView Answer on Stackoverflow