By Mizipzor

2009-02-23 00:30:08 8 Comments

I'm trying to understand the use of super(). From the looks of it, both child classes can be created, just fine.

I'm curious to know about the actual difference between the following 2 child classes.

class Base(object):
    def __init__(self):
        print "Base created"

class ChildA(Base):
    def __init__(self):

class ChildB(Base):
    def __init__(self):
        super(ChildB, self).__init__()



@AnjoMan 2013-10-08 20:08:39

It's been noted that in Python 3.0+ you can use


to make your call, which is concise and does not require you to reference the parent OR class names explicitly, which can be handy. I just want to add that for Python 2.7 or under, some people implement a name-insensitive behaviour by writing self.__class__ instead of the class name, i.e.

super(self.__class__, self).__init__()  # DON'T DO THIS!

HOWEVER, this breaks calls to super for any classes that inherit from your class, where self.__class__ could return a child class. For example:

class Polygon(object):
    def __init__(self, id): = id

class Rectangle(Polygon):
    def __init__(self, id, width, height):
        super(self.__class__, self).__init__(id)
        self.shape = (width, height)

class Square(Rectangle):

Here I have a class Square, which is a sub-class of Rectangle. Say I don't want to write a separate constructor for Square because the constructor for Rectangle is good enough, but for whatever reason I want to implement a Square so I can reimplement some other method.

When I create a Square using mSquare = Square('a', 10,10), Python calls the constructor for Rectangle because I haven't given Square its own constructor. However, in the constructor for Rectangle, the call super(self.__class__,self) is going to return the superclass of mSquare, so it calls the constructor for Rectangle again. This is how the infinite loop happens, as was mentioned by @S_C. In this case, when I run super(...).__init__() I am calling the constructor for Rectangle but since I give it no arguments, I will get an error.

@glglgl 2014-03-31 07:21:33

What this answer suggests, super(self.__class__, self).__init__() does not work if you subclass again without providing a new __init__. Then you have an infinite recursion.

@Veky 2016-07-29 12:54:41

This answer is ridiculous. If you're going to abuse super this way, you might as well just hardcode the base class name. It is less wrong than this. The whole point of first argument of super is that it's not necessarily the type of self. Please read "super considered super" by rhettinger (or watch some of his videos).

@Ryan Hiebert 2017-01-13 16:17:47

The shortcut demonstrated here for Python 2 has pitfalls that have been mentioned already. Don't use this, or your code will break in ways you can't predict. This "handy shortcut" breaks super, but you may not realize it until you've sunk a whole lot of time into debugging. Use Python 3 if super is too verbose.

@Tino 2017-11-21 14:33:51

Edited the answer. Sorry if that edit changes the meaning 180 degrees, but now this answer should make some sense.

@AnjoMan 2017-11-22 02:16:14

@Tino I don't really agree with your edits. It doesn't make sense to say both that one cannot do something and that one shouldn't do it - it is possible to do what I describe in my post, and for the reasons I lay out it is a bad idea.

@Aaron Hall 2017-12-02 23:18:37

What makes no sense is to tell someone they can do something that is trivially demonstrated as incorrect. You can alias echo to python. Nobody would ever suggest it!

@SeasonalShot 2018-08-16 08:09:14

This answer has a point that's all. I wouldn't have thought of doing this since it is a bad design, now that we know, it an be avoided.

@Aaron Hall 2014-11-25 19:00:33

I'm trying to understand super()

The reason we use super is so that child classes that may be using cooperative multiple inheritance will call the correct next parent class function in the Method Resolution Order (MRO).

In Python 3, we can call it like this:

class ChildB(Base):
    def __init__(self):

In Python 2, we are required to use it like this:

super(ChildB, self).__init__()

Without super, you are limited in your ability to use multiple inheritance:

Base.__init__(self) # Avoid this.

I further explain below.

"What difference is there actually in this code?:"

class ChildA(Base):
    def __init__(self):

class ChildB(Base):
    def __init__(self):
        super(ChildB, self).__init__()
        # super().__init__() # you can call super like this in Python 3!

The primary difference in this code is that you get a layer of indirection in the __init__ with super, which uses the current class to determine the next class's __init__ to look up in the MRO.

I illustrate this difference in an answer at the canonical question, How to use 'super' in Python?, which demonstrates dependency injection and cooperative multiple inheritance.

If Python didn't have super

Here's code that's actually closely equivalent to super (how it's implemented in C, minus some checking and fallback behavior, and translated to Python):

class ChildB(Base):
    def __init__(self):
        mro = type(self).mro()             # Get the Method Resolution Order.
        check_next = mro.index(ChildB) + 1 # Start looking after *this* class.
        while check_next < len(mro):
            next_class = mro[check_next]
            if '__init__' in next_class.__dict__:
            check_next += 1

Written a little more like native Python:

class ChildB(Base):
    def __init__(self):
        mro = type(self).mro()
        for next_class in mro[mro.index(ChildB) + 1:]: # slice to end
            if hasattr(next_class, '__init__'):

If we didn't have the super object, we'd have to write this manual code everywhere (or recreate it!) to ensure that we call the proper next method in the Method Resolution Order!

How does super do this in Python 3 without being told explicitly which class and instance from the method it was called from?

It gets the calling stack frame, and finds the class (implicitly stored as a local free variable, __class__, making the calling function a closure over the class) and the first argument to that function, which should be the instance or class that informs it which Method Resolution Order (MRO) to use.

Since it requires that first argument for the MRO, using super with static methods is impossible.

Criticisms of other answers:

super() lets you avoid referring to the base class explicitly, which can be nice. . But the main advantage comes with multiple inheritance, where all sorts of fun stuff can happen. See the standard docs on super if you haven't already.

It's rather hand-wavey and doesn't tell us much, but the point of super is not to avoid writing the parent class. The point is to ensure that the next method in line in the method resolution order (MRO) is called. This becomes important in multiple inheritance.

I'll explain here.

class Base(object):
    def __init__(self):
        print("Base init'ed")

class ChildA(Base):
    def __init__(self):
        print("ChildA init'ed")

class ChildB(Base):
    def __init__(self):
        print("ChildB init'ed")
        super(ChildB, self).__init__()

And let's create a dependency that we want to be called after the Child:

class UserDependency(Base):
    def __init__(self):
        print("UserDependency init'ed")
        super(UserDependency, self).__init__()

Now remember, ChildB uses super, ChildA does not:

class UserA(ChildA, UserDependency):
    def __init__(self):
        print("UserA init'ed")
        super(UserA, self).__init__()

class UserB(ChildB, UserDependency):
    def __init__(self):
        print("UserB init'ed")
        super(UserB, self).__init__()

And UserA does not call the UserDependency method:

>>> UserA()
UserA init'ed
ChildA init'ed
Base init'ed
<__main__.UserA object at 0x0000000003403BA8>

But UserB does in-fact call UserDependency because ChildB invokes super:

>>> UserB()
UserB init'ed
ChildB init'ed
UserDependency init'ed
Base init'ed
<__main__.UserB object at 0x0000000003403438>

Criticism for another answer

In no circumstance should you do the following, which another answer suggests, as you'll definitely get errors when you subclass ChildB:

super(self.__class__, self).__init__()  # DON'T DO THIS! EVER.

(That answer is not clever or particularly interesting, but in spite of direct criticism in the comments and over 17 downvotes, the answerer persisted in suggesting it until a kind editor fixed his problem.)

Explanation: Using self.__class__ as a substitute for the class name in super() breaks the MRO and can lead to recursion. super lets us look up the next parent in the MRO (see the first section of this answer) for child classes. If you tell super we're in the child instance's method, it will then lookup the next method in line (probably this one) resulting in recursion, probably causing a logical failure (in the answerer's example, it does) or a RuntimeError when the recursion depth is exceeded.

>>> class Polygon(object):
...     def __init__(self, id):
... = id
>>> class Rectangle(Polygon):
...     def __init__(self, id, width, height):
...         super(self.__class__, self).__init__(id)
...         self.shape = (width, height)
>>> class Square(Rectangle):
...     pass
>>> Square('a', 10, 10)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in __init__
TypeError: __init__() missing 2 required positional arguments: 'width' and 'height'

@Yohan Obadia 2017-05-29 15:09:21

I'll still need to work my head around this super() function, however, this answer is clearly the best in terms of depth and details. I also appreciate greatly the criticisms inside the answer. It also help to better understand the concept by identifying pitfalls in other answers. Thank you !

@hunch 2017-06-10 14:56:58

@Aaron Hall, thanks for so detailed information. I think there should be one more option available(atleast) to mentors to call some answer as inappropriate or incomplete if they do not provide correct sufficient information.

@Xarses 2018-04-06 19:00:16

Thanks, this was super helpful. The criticism of the poor/improper usage was very illustrative of why, and how to use super

@ioaniatr 2018-08-03 14:40:24

Very good explanation of Python Inheritance. Thanks

@Mike - SMT 2018-11-08 15:55:21

I have been using tk.Tk.__init__(self) over super().__init__() as I didn't fully understand what super was but this post has been very enlightening. I guess in the case of Tkinter classes tk.Tk.__init__(self) and super().__init__() are the same thing but it looks like you are saying we should avoid doing something like Base.__init__(self) so I may be switching to super() even though I am still trying to grasp its complexity.

@physincubus 2019-02-10 20:26:29

this answer is especially comprehensive, and really filled in gaps in my knowledge. hats off to you sir.

@facehugger 2020-02-10 21:33:09

Your second "native Python" example behaves differently than the first example (and as super-based solution). hasattr(next_class, '__init__') used may implicitly indicate the presence of an unnecessary method. For example, imagine canonical diamond hierarchy class A(): ...; class B(A): ...; class C(A): ...; class D(B, C): ... where A and ะก have their own __init__ methods and D has __init__ such as in the described example. Then calling D().__init__() will cause A.__init__ to call instead of C.__init__

@facehugger 2020-02-10 21:34:04

Maybe if '__init__' in next_class.__dict__: is better

@Aaron Hall 2020-02-10 23:12:36

@facehugger it's a translation of a translation - it's not supposed to behave exactly the same, it's supposed to retain the semantics while being as simple as possible.

@Kiv 2009-02-23 00:37:31

super() lets you avoid referring to the base class explicitly, which can be nice. But the main advantage comes with multiple inheritance, where all sorts of fun stuff can happen. See the standard docs on super if you haven't already.

Note that the syntax changed in Python 3.0: you can just say super().__init__() instead of super(ChildB, self).__init__() which IMO is quite a bit nicer. The standard docs also refer to a guide to using super() which is quite explanatory.

@Stevoisiak 2018-02-14 15:34:14

Can you provide an example of super() being used with arguments?

@rimalonfire 2018-05-06 05:22:33

Can you please explain super(ChildB, self).__init__() this , what does ChildB and self have to do with the super

@Omnik 2018-08-30 15:48:43

@rimiro The syntax of super() is super([type [, object]]) This will return the superclass of type. So in this case the superclass of ChildB will be returned. If the second argument is omitted, the super object returned is unbound. If the second argument is an object, then isinstance(object, type) must be true.

@eric 2019-02-18 23:53:43

If you are here and still confused, please read the answer by Aaron Hall you will leave this page much happier:

@Charlie Parker 2019-06-04 23:00:59

can you actually explain what the code does? I don't want to click to 1 million more places to find the answer to this.

@RubenLaguna 2015-09-21 06:41:03

The main difference is that ChildA.__init__ will unconditionally call Base.__init__ whereas ChildB.__init__ will call __init__ in whatever class happens to be ChildB ancestor in self's line of ancestors (which may differ from what you expect).

If you add a ClassC that uses multiple inheritance:

class Mixin(Base):
  def __init__(self):
    print "Mixin stuff"
    super(Mixin, self).__init__()

class ChildC(ChildB, Mixin):  # Mixin is now between ChildB and Base

help(ChildC) # shows that the the Method Resolution Order is ChildC->ChildB->Mixin->Base

then Base is no longer the parent of ChildB for ChildC instances. Now super(ChildB, self) will point to Mixin if self is a ChildC instance.

You have inserted Mixin in between ChildB and Base. And you can take advantage of it with super()

So if you are designed your classes so that they can be used in a Cooperative Multiple Inheritance scenario, you use super because you don't really know who is going to be the ancestor at runtime.

The super considered super post and pycon 2015 accompanying video explain this pretty well.

@nispio 2015-11-13 04:17:32

This. The meaning of super(ChildB, self) changes depending on the MRO of the object referred to by self, which cannot be known until runtime. In other words, the author of ChildB has no way of knowing what super() will resolve to in all cases unless they can guarantee that ChildB will never be subclassed.

@S C 2012-11-27 23:26:47

Super has no side effects

Base = ChildB


works as expected

Base = ChildA


gets into infinite recursion.

@Aaron Hall 2017-10-01 00:53:01

The statement, "Super has no side effects," doesn't make sense in this context. Super simply guarantees we call the correct next class's method in the method resolution order, whereas the other way hard-codes the next method to be called, which makes cooperative multiple inheritance more difficult.

@rgenito 2012-05-25 17:52:49

Just a heads up... with Python 2.7, and I believe ever since super() was introduced in version 2.2, you can only call super() if one of the parents inherit from a class that eventually inherits object (new-style classes).

Personally, as for python 2.7 code, I'm going to continue using BaseClassName.__init__(self, args) until I actually get the advantage of using super().

@andilabs 2013-07-19 11:38:34

very good point. IF you don't clearly mention: class Base(object): then you will get error like that: "TypeError: must be type, not classobj"

@Two-Bit Alchemist 2016-05-05 13:56:52

@andi I got that error the other day and I eventually just gave up trying to figure it out. I was just messing around on iPython. What a freaking nightmare of a bad error message if that was actually code I had to debug!

@Devin Jeanpierre 2009-02-23 00:34:57

There isn't, really. super() looks at the next class in the MRO (method resolution order, accessed with cls.__mro__) to call the methods. Just calling the base __init__ calls the base __init__. As it happens, the MRO has exactly one item-- the base. So you're really doing the exact same thing, but in a nicer way with super() (particularly if you get into multiple inheritance later).

@Mizipzor 2009-02-23 00:40:39

I see. Could you elaborate a little as to why its nicer to use super() with multiple inheritance? To me, the base.__init__(self) is shorter (cleaner). If I had two baseclasses, it would be two of those lines, or two super() lines. Or did I misunderstand what you meant by "nicer"?

@Devin Jeanpierre 2009-02-23 00:45:12

Actually, it would be one super() line. When you have multiple inheritance, the MRO is still flat. So the first super().__init__ call calls the next class's init, which then calls the next, and so on. You should really check out some docs on it.

@James Brady 2009-02-23 01:24:38

The child class MRO contains object too - a class's MRO is visible in the mro class variable.

@James Brady 2009-02-23 01:26:32

Also note that classic classes (pre 2.2) don't support super - you have to explicitly refer to base classes.

@Devin Jeanpierre 2009-02-23 04:14:39

"The child class MRO contains object too - a class's MRO is visible in the mro class variable." That is a big oops. Whoops.

@nispio 2015-11-13 04:25:44

To say that "the MRO has exactly one item" assumes that ChildB will never be subclassed. You don't actually know until runtime what the MRO will be when the call to super() happens.

Related Questions

Sponsored Content

26 Answered Questions

[SOLVED] Does Python have a ternary conditional operator?

20 Answered Questions

[SOLVED] Are static class variables possible in Python?

62 Answered Questions

[SOLVED] Calling an external command from Python

6 Answered Questions

[SOLVED] Python class inherits object

10 Answered Questions

[SOLVED] Does Python have a string &#39;contains&#39; substring method?

20 Answered Questions

[SOLVED] What are metaclasses in Python?

15 Answered Questions

[SOLVED] Call a parent class's method from child class?

15 Answered Questions

[SOLVED] How does Python's super() work with multiple inheritance?

32 Answered Questions

[SOLVED] Understanding slice notation

11 Answered Questions

[SOLVED] What is for?

Sponsored Content