Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between super() and Parent class name?

Is there a difference between using super() and using the parent class name directly? For example:

class Parent:     def __init__(self):         print("In parent")         self.__a=10  class Child(Parent):     def __init__(self):         super().__init__()     # using super()         Parent.__init__(self)  # using Parent class name  c=Child() 

Is there internally a difference between super().__init__() and Parent.__init__(self)?

like image 394
codingsplash Avatar asked Feb 23 '17 10:02

codingsplash


People also ask

Is Super class same as parent class?

Definitions: A class that is derived from another class is called a subclass (also a derived class, extended class, or child class). The class from which the subclass is derived is called a superclass (also a base class or a parent class).

Is super class the same as parent class in Java?

They are essentially the same. Depending on the language, the terminology changes. Parent may mean the immediate parent, while Super class may mean any of the ancestor classes. In addition, in java, there is the super() method, which calls the parent's constructor.

What does super () mean?

Definition and Usage The super() function is used to give access to methods and properties of a parent or sibling class. The super() function returns an object that represents the parent class.

What is the use of super () in Java?

The super keyword refers to superclass (parent) objects. It is used to call superclass methods, and to access the superclass constructor. The most common use of the super keyword is to eliminate the confusion between superclasses and subclasses that have methods with the same name.


1 Answers

Not in this case. But in general, and especially when you use multiple inheritance, super() delegates to the next object in the Method Resolution Order (MRO) as is specified in the documentation:

super([type[, object-or-type]])

Return a proxy object that delegates method calls to a parent or sibling class of type. This is useful for accessing inherited methods that have been overridden in a class. The search order is same as that used by getattr() except that the type itself is skipped.

The __mro__ attribute of the type lists the method resolution search order used by both getattr() and super(). The attribute is dynamic and can change whenever the inheritance hierarchy is updated.

(...)

(copied, boldface added)

Say for instance you define classes like (borrowed from this question, where the MRO is discussed in more detail):

class F:     def __init__(self):         print('F%s'%super().__init__)         super().__init__()  class G:      def __init__(self):         print('G%s'%super().__init__)         super().__init__()   class H:      def __init__(self):         print('H%s'%super().__init__)         super().__init__()  class E(G,H):     def __init__(self):         print('E%s'%super().__init__)         super().__init__()  class D(E,F):      def __init__(self):         print('D%s'%super().__init__)         super().__init__()   class C(E,G):      def __init__(self):         print('C%s'%super().__init__)         super().__init__()  class B(C,H):      def __init__(self):         print('B%s'%super().__init__)         super().__init__()  class A(D,B,E):      def __init__(self):         print('A%s'%super().__init__)         super().__init__() 

Then the __mro__ of A is:

A.__mro__ == (A,D,B,C,E,G,H,F,object) 

Now if we call A(), it prints:

A<bound method D.__init__ of <__main__.A object at 0x7efefd8645c0>> D<bound method B.__init__ of <__main__.A object at 0x7efefd8645c0>> B<bound method C.__init__ of <__main__.A object at 0x7efefd8645c0>> C<bound method E.__init__ of <__main__.A object at 0x7efefd8645c0>> E<bound method G.__init__ of <__main__.A object at 0x7efefd8645c0>> G<bound method H.__init__ of <__main__.A object at 0x7efefd8645c0>> H<bound method F.__init__ of <__main__.A object at 0x7efefd8645c0>> F<method-wrapper '__init__' of A object at 0x7efefd8645c0> <__main__.A object at 0x7efefd8645c0> 

so it means that in the context of A and when trying to obtain __init__ that:

  • super().__init__ of A is D.__init__;
  • super().__init__ of D is B.__init__;
  • super().__init__ of B is C.__init__;
  • super().__init__ of C is E.__init__;
  • super().__init__ of E is G.__init__;
  • super().__init__ of G is H.__init__;
  • super().__init__ of H is F.__init__; and
  • super().__init__ of F is object.__init__.

Note thus that super() does not per se delegates to a parent. For instance the super() of D is B and B is not a superclass of D, so it really depends on the type of the object (not on the class).

Now in case of D, the __mro__ is:

D.__mro__ = (D,E,G,H,F,object) 

If we construct a D however we get:

D<bound method E.__init__ of <__main__.D object at 0x7efefd864630>> E<bound method G.__init__ of <__main__.D object at 0x7efefd864630>> G<bound method H.__init__ of <__main__.D object at 0x7efefd864630>> H<bound method F.__init__ of <__main__.D object at 0x7efefd864630>> F<method-wrapper '__init__' of D object at 0x7efefd864630> 

So in the context of D it holds that:

  • super().__init__ of D is E.__init__;
  • super().__init__ of E is G.__init__;
  • super().__init__ of G is H.__init__;
  • super().__init__ of H is F.__init__; and
  • super().__init__ of F is object.__init__.

So here the super() of D leads to E (for __init__) which is not the same in the context of A.

like image 158
Willem Van Onsem Avatar answered Sep 30 '22 12:09

Willem Van Onsem