Is the __init__ method a class?

I studied the Python super method and multiple inheritance. I read something like when we use super to call a base method that has an implementation in all base classes, only one class method will be called even with many arguments. For instance,

class Base1(object): def __init__(self, a): print "In Base 1" class Base2(object): def __init__(self): print "In Base 2" class Child(Base1, Base2): def __init__(self): super(Child, self).__init__('Intended for base 1') super(Child, self).__init__()# Intended for base 2 

This creates a TyepError for the first super method. super will call some implementation of the method that it first recognizes, and gives a TypeError instead of checking other classes along the way. However, it will be much clearer and work fine if we do the following:

 class Child(Base1, Base2): def __init__(self): Base1.__init__(self, 'Intended for base 1') Base2.__init__(self) # Intended for base 2 

This leads to two questions:

  • Is the __init__ method a static method or a class method?
  • Why use a super one that implicitly selects a method on its own, rather than an explicit method call like the last example? It looks a lot cleaner than using super for me. So, what is the advantage of using super in the second way (other than writing the name of the base class when calling the method)
+6
source share
2 answers

super() before multiple inheritance, especially for methods present on object can get a little confused . The general rule is that if you use super , then every class in the hierarchy should use super . A good way to handle this for __init__ is to make each method **kwargs and always use keyword arguments everywhere. By the time the call to object.__init__ all arguments must be popped up!

 class Base1(object): def __init__(self, a, **kwargs): print "In Base 1", a super(Base1, self).__init__() class Base2(object): def __init__(self, **kwargs): print "In Base 2" super(Base2, self).__init__() class Child(Base1, Base2): def __init__(self, **kwargs): super(Child, self).__init__(a="Something for Base1") 

Check out the related article to learn more about how it works and how to make it work for you!

Edit: risking answering two questions: "Why use super at all?"

We have super() for many of the same reasons that we have classes and inheritance, as a tool for modulating and abstracting our code. When working with an instance of a class, you do not need to know all the detailed information about how this class was implemented, you only need to know its methods and attributes, as well as how you should use this open interface for the class. In particular, you can be sure that changes to the class implementation cannot cause problems as a user of its instances.

The same argument applies when getting new types from base classes. You do not want or should not worry about how these base classes were implemented. Here's a concrete example of how not to use super, could go wrong. suppose you have:

 class Foo(object): def frob(self): print "frobbign as a foo" class Bar(object): def frob(self): print "frobbign as a bar" 

and you create a subclass:

 class FooBar(Foo, Bar): def frob(self): Foo.frob(self) Bar.frob(self) 

Everything is fine, but then you understand that when you start it, Foo really is a kind of Bar , so you change it

  class Foo(Bar): def frob(self): print "frobbign as a foo" Bar.frob(self) 

That everything is fine, except that in your derived class, FooBar.frob() calls Bar.frob() twice.

This is the exact problem super() solves, it protects you from calling superclass implementations more than once (when used as intended ...)

+11
source

As for your first question, __init__ is neither a staticmethod nor a classmethod; This is a common instance method. (That is, he receives the instance as his first argument.)

As for your second question, if you want to explicitly call several implementations of the base class, then doing it explicitly, like you, is really the only way. However, it seems you do not understand how super works. When you call super , it does not β€œknow” if you have already called it. Both of your calls to super(Child, self).__init__ invoke the Base1 implementation because it is the β€œclosest parent” (the most immediate superclass from Child ).

You would use super if you want to call this immediate implementation of the superclass. You would do this if this superclass were also configured to invoke your superclass, etc. The way you use super is to have each class only call the next up implementation in the class hierarchy, so that the sequence of super calls on the whole calls everything you need to call, in the correct order. This type of customization is often called "shared inheritance," and you can find various articles about it on the Internet, including here and here .

+8
source

Source: https://habr.com/ru/post/982662/


All Articles