Is __init__ a class method?
inheritance, multiple-inheritance, python, python-2.7
Solution
`super()` in the face of multiple inheritance, especially on methods that are present on `object` can get a bit tricky. 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 every method take `**kwargs`, and always use keyword arguments everywhere. By the time the call to `object.__init__` occurs, all arguments should have been popped out!
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")
See the linked article for way more explanation of how this works and how to make it work for you!
Edit: At the risk of answering two questions, "Why use super at all?"
We have `super()` for many of the same reasons we have classes and inheritance, as a tool for modularizing and abstracting our code. When operating on an instance of a class, you don't need to know all of the gritty details of how that class was implemented, you only need to know about its methods and attributes, and how you're meant to use that public interface for the class. In particular, you can be confident that changes in the implementation of a class can't cause you problems as a user of its instances.
The same argument holds when deriving new types from base classes. You don't want or need to worry about how those base classes were implemented. Here's a concrete example of how not using super might go wrong. suppose you've got:
class Foo(object):
def frob(self):
print "frobbign as a foo"
class Bar(object):
def frob(self):
print "frobbign as a bar"
and you make a subclass:
class FooBar(Foo, Bar):
def frob(self):
Foo.frob(self)
Bar.frob(self)
Everything's fine, but then you realize that when you get down to 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)
Which is all 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 directed...)
Problem
I was looking into Python's super method and multiple inheritance. I read along something like when we use super to call a base method which has implementation in all base classes, only one class' method will be called even with variety of arguments. For example, ``` 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 produces `TyepError` for the first `super` method. `super` would call whichever method implementation it first recognizes and gives `TypeError` instead of checking for other classes down the road. However, this will be much more clear and work fine when 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 `__init__` method a static method or a class method? - Why use super, which implicitly choose the method on it's own rather than explicit call to the method like the latter example? It looks lot more cleaner than using super to me. So what is the advantage of using `super` over the second way(other than writing the base class name with the method call)