views:

6870

answers:

4

I was reading 'Dive Into Python' and in the chapter on classes it gives this example:

class FileInfo(UserDict):
    "store file metadata"
    def __init__(self, filename=None):
        UserDict.__init__(self)
        self["name"] = filename

The author then says that if you want to override the __init__ method, you must explicitly call the parent __init__ with the correct parameters. What if that FileInfo class had more than one ancestor class? Do I have to explicitly call all of the ancestor classes' __init__ methods? Also, do I have to do this to any other method I want to override?

+2  A: 

If the FileInfo class has more than one ancestor class then you should definitely call all of their __init__() functions. You should also do the same for the __del__() function, which is a destructor.

marcog
+16  A: 

The book is a bit dated with respect to subclass-superclass calling. It's also a little dated with respect to subclass built-in classes.

It looks like this nowadays.

class FileInfo(dict):
    """store file metadata"""
    def __init__(self, filename=None):
        super( FileInfo, self ).__init__()
        self["name"] = filename

Note the following.

  1. We can directly subclass built-in classes, like dict, list, tuple, etc.

  2. The super function handles tracking down this class's superclasses and calling functions in them appropriately.

S.Lott
should i look for a better book/tutorial?
David McDavidson
So in the case of multiple inheritance, does super() track them all down on your behalf?
Dana
What is wrong with dict.__init__(), exactly?
Bastien Léonard
dict.__init__(self), actually, but nothing's wrong with it - the super(...) call just provides a more consistent syntax. (I'm not sure how it works for multiple inheritance, I think it may only find one superclass __init__)
David Zaslavsky
The intention of super() is that it handles multiple inheritance. The disadvantage is, that in practice multiple inheritance still breaks very easily (see <http://fuhm.net/super-harmful/ ).
sth
Yes, in case of multiple inheritance and base classes taking constructor arguments, you usually find yourself calling the constructors manually.
Torsten Marek
@bullettime: you can try mine -- it might not be enough better -- but here it is: http://homepage.mac.com/s_lott/books/python.html
S.Lott
A: 

Yes, you must call __init__ for each parent class. The same goes for functions, if you are overriding a function that exists in both parents.

vezult
+5  A: 

You don't really have to call the __init__ methods of the base class(es), but you usually want to do it because the base classes will do some important initializations there that are needed for rest of the classes methods to work.

For other methods it depends on your intentions. If you just want to add something to the base classes behavior you will want to call the base classes method additionally to your own code. If you want to fundamentally change the behavior, you might not call the base class' method and implement all the functionality directly in the derived class.

sth
For technical completeness, some classes, like threading.Thread, will throw gigantic errors if you ever try to avoid calling the parent's __init__.
David Berger