Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Abstract base class: raise NotImplementedError() in `__init__.py`?

Tags:

python

pycharm

PyCharm warns me Call to __init__ of super class is missed

class AbstractBase(object):
    def __init__(self):
        raise NotImplementedError()

class RealChild(AbstractBase):
    def __init__(self):
        #super(RealChild, self).__init__() ####
        print('do stuff')

child=RealChild()

But if I call it, the class AbstractBase will raise NotImplementedError.

I am a sheep and don't know how to proceed :-)

like image 482
guettli Avatar asked Sep 03 '15 09:09

guettli


People also ask

What does raise NotImplementedError () do?

Raise NotImplementedError to indicate that a super-class method is not implemented and that child classes should implement it.

How do you raise NotImplementedError in Python?

If you run into the NotImplementedError, the recommended way to handle it is to implement the abstract method for which the error is being raised. Because the NotImplementedError is user-defined, Python can't raise this error on its own. So, you'll need to raise it by a package you're using or code your team wrote.

How do I fix NotImplementedError in Python?

The NotImplementedError is raised when you do not implement the abstract method in the child class. This error can be solved by using the abstract method in every child class. If we use the abstract method inside the child class, a new instance of that method is created inside the child class.

When should a NotImplementedError be raised?

Python NotImplementedError Exception occurs at runtime when client characterized base classes; conceptual techniques should raise this exception when they require inferred classes to abrogate the strategy or while the class is being created to demonstrate that the genuine usage despite everything should be included.


2 Answers

You might consider using the abc Abstract Base Class module to mark __init__ as abstract, and then go ahead and invoke the superclass __init__ from the subclass (and, as DorElias suggested, give the superclass __init__ a trivial implementation of pass):

from abc import ABCMeta, abstractmethod


class AbstractBase(object, metaclass=ABCMeta):
    @abstractmethod  # This method must be overridden...
    def __init__(self):
        print("...but can still be called via super by subclasses have shared construction logic")
        pass


class RealChild(AbstractBase):
    def __init__(self):
        super().__init__()  # Won't do anything, UNTIL the day you decide all subclasses of AbstractBase need shared logic
        print('do stuff')


child = RealChild()

If you try to instantiate via parent = AbstractBase() or parent = AbstractBase.__new__(AbstractBase), you'll get an error:

TypeError: Can't instantiate abstract class AbstractBase with abstract methods init

So you've got your uninstantiable abstract safety, but at the same time you are still well set up to alter all child class construction by altering base class construction, as is right and proper.

like image 52
Bryant Avatar answered Oct 08 '22 04:10

Bryant


You could do something kind-of ugly and check the type of self in the abstract type’s initializer to make sure that it was subtyped:

class AbstractBase (object):
    def __init__ (self):
        if type(self) is AbstractBase:
            raise NotImplementedError

I think a more “normal” approach would be to simply not expose the abstract base type and expect users not to create it.

like image 34
poke Avatar answered Oct 08 '22 04:10

poke