8

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

guettli
  • 25,042
  • 81
  • 346
  • 663

4 Answers4

8

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.

Community
  • 1
  • 1
Bryant
  • 622
  • 4
  • 18
  • This should be the accepted answer. If the intent is to have an ABC, be explicit about it -- raising an exception in the constructor is not the way to do this. – BoltzmannBrain Oct 28 '16 at 18:19
  • Using `@abstractmethod` is better, but calling the super `__init__` just to avoid the Pycharm warning feels wrong. The super `__init__` doesn't do anything. – oulenz Jul 20 '20 at 15:04
4

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.

poke
  • 369,085
  • 72
  • 557
  • 602
  • How can I "not expose the abstract base type"? Other developers need to subclass it. – guettli Sep 07 '15 at 09:05
  • Developers yes, but users don’t. So only make it available to developers who know it shouldn’t be instanced on its own. In general, don’t go too far to enforce rules, but just document it clearly and expect people to do it correctly. – poke Sep 07 '15 at 09:14
  • I still don't get it. My users know how to use a web browser. The don't know that Python is a programming language. I guess "don't expose the abstract base type" does not work in my case. – guettli Sep 07 '15 at 09:31
0

In the abstract class replace the exception in the init function with

pass

This exception is used to prevent you from initializing new instance of the abstract class (it is abstract, so you can't) So either use 'pass' or don't listen to pycharm and don't call super

DorElias
  • 2,243
  • 15
  • 18
  • 2
    Technically, the exception prevents you from initializing a new object, not creating it. `a = A.__new__(A)` works fine. – chepner Sep 03 '15 at 11:40
0

The answer by @Bryant correctly explains that you should use @abstractmethod instead of manually raising a NotImplementedError.

This allows you to call the super __init__, but it doesn't necessarily mean that you should, since it still doesn't do anything. It's a matter of personal taste, and Pycharm is wrong to issue a warning over it.

So my alternative answer is: ignore Pycharm and hope that they fix this some day.

oulenz
  • 1,199
  • 1
  • 15
  • 24