2

I am trying to write a base abstract class that has some properties that will be initialized using a constructor. So far I have this:

from abc import ABC, abstractmethod

class A(ABC):
    def __init__(self, n, *params):
        self.n = n
        self.initialize_params(*params) #I want to do this in all subsclasses of A
    def initialize_params(self, *params)
       pass
    @abstractmethod
    def do(self):
        pass

class B(A):
    def __init__(self, m, n, *super_params):
        self.m = m
        super(A, self).__init__(n, *super_params)
    def do(self):
        print("this is B")

But this will throw TypeError because of instantiation of A in __init__ of B. What is the correct way of doing this?

martineau
  • 119,623
  • 25
  • 170
  • 301
Farhood ET
  • 1,432
  • 15
  • 32

1 Answers1

4

You seem to have a couple of mistakes:

from abc import ABC, abstractmethod

class A(ABC):
    def __init__(self, n, *params):
        self.n = n
        self.initialize_params(*params) #I want to do this in all subsclasses of A
    def initialize_params(self, *params):
        pass
    @abstractmethod
    def do(self):
        pass

class B(A):
    def __init__(self, m, n, *super_params):
        self.m = m
        super().__init__(n, *super_params)  # correct way to use super() to call init
    def do(self):
        print("this is B")


b = B(1,2)
b.do()

Note that you missed self. infront of initialize_params() and you didn't seem to be using super() correctly.

quamrana
  • 37,849
  • 12
  • 53
  • 71
  • Sorry for the errors. I typed the question on the fly. I'm curious to know why calling `super` this way is different than `super(supercls, self)`. Since it's only a python3 functionality for the same call IIRC. – Farhood ET Mar 29 '21 at 10:48
  • 3
    @FarhoodET **`super(supercls, self)`** is never how you should be calling `super`. It's always `super(the_class_where_its_being_called, self).foo()`, although, in Python 3, you can just use the no-argument form, `super().foo()`, which will be the equivalent of the correct version. – juanpa.arrivillaga Mar 29 '21 at 10:51
  • @juanpa.arrivillaga oh you're right! Sorry for the confusion. But what about multiple inheritance in python? How does one indicate which superclass initializer is called first? or is it a non-issue? – Farhood ET Mar 29 '21 at 10:53
  • 1
    @FarhoodET if you want to call a *specific* method, you wouldn't use super, you would just use `TheSpecifcClass.foo(self)`. The whole point of `super` is to *delegate to the next class in the method resolution order*. So it takes `super(type, obj)`, where `isinstance(obj, type)`. It *skips* `type` in the method-resolution order of `type(obj)`. [Read the docs](https://docs.python.org/3/library/functions.html#super). Also, [this guide will be useful](https://rhettinger.wordpress.com/2011/05/26/super-considered-super/) – juanpa.arrivillaga Mar 29 '21 at 10:57
  • 1
    @FarhoodET in fact, [here's a video version of that guide](https://www.youtube.com/watch?v=EiOglTERPEo) – juanpa.arrivillaga Mar 29 '21 at 11:00