1

I just noticed some unintended behaviour then tested it in an interpretor (Python 3.5.3):

>>> class SomeClass:
...     def __init__(self):
...         print("nothing important")
... 
>>> a = SomeClass()
nothing important
>>> class SomeOtherClass(SomeClass):
...     pass
... 
>>> b = SomeOtherClass()
nothing important
>>> 

I thought you needed to directly call the parents __init__(). What is the simplest way to write or instantiate the child class such that it does not run the __init__() from the parent class?

cardamom
  • 6,873
  • 11
  • 48
  • 102
  • 1
    The whole point of inheritance is code reuse. You could override `__init__` in the subclass. Maybe you don't want inheritance at all? – timgeb Jan 08 '19 at 12:39
  • 1
    No, I want some methods from the parent, just not that the init runs. – cardamom Jan 08 '19 at 12:40
  • 1
    define `__init__` in `SomeOtherClass` as well? – AverageJoe9000 Jan 08 '19 at 12:41
  • *Not* calling `__init__` breaks the contract that an instance of `SomeOtherClass` is-a instance of `SomeClass`. Consider that `SomeClass.__init__` should be redefined. – chepner Jan 08 '19 at 13:03

2 Answers2

4

You can by defining an __init__ method in the child class:

class SomeOtherClass(SomeClass):
  def __init__(self):
    pass
DjaouadNM
  • 22,013
  • 4
  • 33
  • 55
  • 1
    Remember that this implementation will be passed along to subclasses of `SomeOtherClass`. You are not "deactivating" `__init__` for a single class here (unless there are no further subclasses). – timgeb Jan 08 '19 at 12:42
  • Thanks, okay well it looks like you just have overwrite it. I thought there might have been some kind of trick to stop it running when you inherit or instantiate it. – cardamom Jan 08 '19 at 12:44
  • @cardamom you're welcome. @timgeb That's a very good observation, but that may be what the OP wants, maybe there will be no more subclasses, and if there are, won't this `SomeClass.__init__(self)` solve the problem? – DjaouadNM Jan 08 '19 at 12:47
  • @MrGeek It does make a lot of the code with `super().__init__(self)` and `Base.__init__(self)` in [this answer](https://stackoverflow.com/questions/576169/understanding-python-super-with-init-methods) seem rather redundant if it calls on instantiation anyway.. – cardamom Jan 08 '19 at 12:49
  • 2
    @cardamom Not exactly, most of time the subclasses contain additional information and are therefore instantiated differently from their parent class, e.g.: `Shape()` may have an `area` property, subclass `Circle(Shape)` has a `radius`, and `Shape` class doesn't have, so more variable instantiations is required in the `__init__()` of the `Circle` class, after the `super.__init__()`, which initializes `Circle` objects with properties that are both in `Circle` and in `Shape`. – DjaouadNM Jan 08 '19 at 13:02
  • 1
    Thanks @MrGeek this questions seems to have stirred up some emotions in the community.. Now that I think of it, it is probably more pythonic to turn the methods I need into `@staticmethod` 's than to instantiate it and suppress the init like this. – cardamom Jan 08 '19 at 13:12
  • @cardamom You're welcome, and it's up to you what style you choose. – DjaouadNM Jan 08 '19 at 13:19
  • @cardamom If you want only to reuse part of the code (implementation inheritance, vs type inheritance), then you should extract common behaviours into a mixin class (a class that only have behaviors - no state) and make both `SomeClass` and `SomeOtherClass` inherit from this mixin. – bruno desthuilliers Jan 08 '19 at 13:21
3

I want some methods from the parent, just not that the init runs

Then your design is wrong. If you only care about code reuse but not proper subtyping (as defined by Liskov), proper designs are either composition/delegation or (probably the best in your case) multiple inheritance with mixin classes:

class CommonMixin():
    def method1(self):
       pass

    def method2(self):
       pass


class SomeClass(CommonMixin, SomeBaseClass):
    def __init__(self):
        print("nothing important")


class SomeOtherClass(CommonMixin, SomeOtherBaseClass):
    pass
bruno desthuilliers
  • 75,974
  • 6
  • 88
  • 118