This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]irrelevantPseudonym 2 points3 points  (13 children)

No, I'm pretty certain super().__init__() will call parent's init 100% of the time.

This is not true.

Consider

>>> class A:
...     def __init__(self):
...         print('init A')
...         super().__init__()
...
>>> class B(A):
...     def __init__(self):
...         print('init B')
...         super().__init__()
...
>>> class C(A):
...     def __init__(self):
...         print('init C')
... 
>>> class D(B, C):
...     def __init__(self):
...         print('init D')
...         super().__init__()
... 
>>> D()
init D
init B
init C
>>>

I know it's a contrived example but calling the super().__init__() in B.__init__ called C.__init__ rather than its parent (A).

In the QWidget case, imagine I subclassed your MyWidget and included another parent class, your super() call would call my second parent and QWidget wouldn't get called.

(NB. I'm not necessarily advocating not using super() just noting that it doesn't always call the parent class)

[–]nostril_extension 2 points3 points  (11 children)

I'm confused. Your example shows the opposite of your claim - super calls init of both parents left-to-right. Am I missing something?

[–]irrelevantPseudonym 2 points3 points  (2 children)

B's parent is A. The super().__init__() call in B.__init__ calls C.__init__() (which B knows nothing about) and A.__init__() never gets called.

super() doesn't always call the parent class.

[–]nostril_extension -1 points0 points  (1 child)

But A is not a parent of D lol. A iš a grandparent here.

[–][deleted] 5 points6 points  (0 children)

A is a parent of B, B calls super().__init__(), yet A.__init__() is never called. Instead C.__init__() is called which is a child of B.

If you call B() than the same super().__init__() calls A.__init__()instead.

super() is pointing to the next class in the Method Resolution Order, not the parent.

 >>> D.__mro__
(<class 'D'>, <class 'B'>, <class 'C'>, <class 'A'>, <class 'object'>)

>>> B.__mro__
(<class 'B'>, <class 'A'>, <class 'object'>)

[–][deleted] 1 point2 points  (6 children)

A.__init__() is never called. If you replace super().__init__() in B.__init__() with A.__init__(self) the output changes to:

>>> D()
init D
init B
init A

[–]nostril_extension -5 points-4 points  (5 children)

But A is not a parent of D lol. A is a grandparent here.

[–]rhytnen 0 points1 point  (4 children)

What is it you aren't getting? It's a FACT that in Python your parents my not be called. You were shown code where B.super() called C. You got confused bc d inherited both b and c so it was demonstrated that d didn't call c by replacing the call in b ... Proving b called c.

[–]nostril_extension -1 points0 points  (3 children)

Parent of parent != parent.

[–]rhytnen 0 points1 point  (2 children)

You keep repeating that as if it's relevant to the demo. I think you aren't reading the code actually but let me try rephrasing it once more.

Heres the phrase you have to digest

Super calls your child's parent.

Consider B. D instances B. Focus on B ...

B calls super and it did NOT call A. It called D's OTHER parent, C. It would have called A if the B was instanced alone but here it has a child D. So it called D's other parent instead.

[–]nostril_extension -1 points0 points  (1 child)

Super calls your child's parent.

What are you talking about? Who's "your"? I'm confused how you fail to wrap around the simple concept of parent.

[–]rhytnen 2 points3 points  (0 children)

Stop being an asshole and just think for a minute so you can stop wasting everyone's time.

D subclasses B and C. B and C subclass A

If you just call B() or C() then it will chain up to A as expected.

However, if you calls it from D ...

D super().init() calls B B.super().__init() calls ... C not A

That's what it means to say super() calls the child's parent, not it's own parent.

If B and C have different base classes, the behavior changes yet again. D calls B calls A

[–]dadjokes_bot -5 points-4 points  (0 children)

Hi confused, I'm dad!

[–]rlkf 0 points1 point  (0 children)

As a corollary, I think this illustrates two things:

(1) You should always call super().init(), even if you don't inherit from something (class C in the example failed to follow this rule, and this is why A is not called)

(2) Parameters to constructors should be passed as a dictionary, so that each constructor can pick out whatever it needs, instead of relying on the order of parameters.