2

I am trying to figure how to use super() to initialize the parent class one by one based on condition.

class A:
 def __init__(self, foo):
 self.foo = foo
class B:
 def __init__(self, bar):
 self.bar == bar
class C(A,B):
 def __init__(self):
 #Initialize class A first.
 #Do some calculation and then initialize class B 

How do I use super() in class C such that it only initializes class A first, then I do some calc and call super() to initialize class B

asked Feb 6, 2019 at 20:18
1
  • The biggest misunderstanding about super().foo() is that it isn't just a shortcut for for cls in parent_classes: cls.foo(self). Commented Feb 6, 2019 at 20:46

2 Answers 2

4

You cannot do what you ask for in C.__init__, as super doesn't give you any control over which specific inherited methods get called, only the order in which they are called, and that is controlled entirely by the order in which the parent classes are listed.

If you use super, you need to use it consistently in all the classes. (That's why it's called cooperative inheritance.) Note this means that C cannot inject any code between the calls to A.__init__ and B.__init__.

__init__ is particularly tricky to implement correctly when using super, because a rule of super is that you have to expected arbitrary arguments to be passed, yet object.__init__() doesn't take any arguments. You need each additional argument to be "owned" by a particular root class that is responsible for removing it from the argument list.

class A:
 def __init__(self, foo, **kwargs):
 # A "owns" foo; pass everything else on
 super().__init__(**kwargs)
 self.foo = foo
class B:
 def __init__(self, bar, **kwargs):
 # B "owns" bar; pass everything else on
 super().__init__(**kwargs)
 self.bar = bar
class C(A,B):
 def __init__(self):
 # Must pass arguments expected by A and B
 super().__init__(foo=3, bar=9)

The MRO for C is [A, B, object], so the call tree looks something like this:

  1. C.__init__ is called with no arguments
  2. super() resolves to A, so A.__init__ is called with foo=3 and bar=9.
  3. In A.__init__, super() resolves to B, so B.__init__ is called with bar=9.
  4. In B.__init__, super() resolves to object, so object.__init__ is called with no arguments (kwargs being empty)
  5. Once object.__init__ returns, self.bar is set to bar
  6. Once B.__init__ returns, self.foo is set to foo
  7. Once A.__init__ returns, C.__init__ finishes up

OK, the first sentence isn't entirely true. Since neither A nor B, as currently written, use super, you might be able to assume that an appropriate use of super will simply call one parent function and immediately return.

class A:
 def __init__(self, foo):
 self.foo = foo
class B:
 def __init__(self, bar):
 self.bar == bar
class C(A,B):
 def __init__(self):
 super(A, self).__init__(foo=3)
 # Do some calculation
 super(B, self).__init__(bar=9)

I'm not entirely certain, though, that this doesn't introduce some hard-to-predict bugs that could manifest with other subclasses of A, B, and/or C that attempt to use super properly.

answered Feb 6, 2019 at 20:44
Sign up to request clarification or add additional context in comments.

Comments

0

You can actually refer the base classes explicitly:

class A:
 def __init__(self, foo):
 self.foo = foo
class B:
 def __init__(self, bar):
 self.bar == bar
class C(A,B):
 def __init__(self):
 A.__init__(self, 'foovalue')
 # Do some calculation
 B.__init__(self, 'barvalue')
answered Feb 6, 2019 at 20:22

2 Comments

Thanks Philip, but I am trying to figure how would I achieve this with super()
super() returns a proxy object that allows you to make method calls to the parent classes by the order defined in __mro__ attribute. Since you want to explicitly initialize class A and class B, the only way is to call each initializer method explicitly - you need to tell Python which initializer you want to call.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.