__init__

Guido.van.Rossum@cwi.nl
Tue, 18 May 1993 00:37:00 +0200

The next Python release will have a feature that makes initialization
of class instances a little easier. If a class defines a method named
__init__ then this method will be called when an instance of that
class is created. If you pass any arguments to the class these will
be passed on to the __init__ method. For example:

class Window:
def __init__(self, name):
self.name = name
"other initializations"
"other methods"

x = Window('testWindow')

Now think of derived classes. If the derived class also calls a
method named __init__, it will be called. But shouldn't the base
class's __init__ be called first? Any C++ programmer would recognize
that __init__ is really a "constructor", and in C++ constructors of
base classes are guaranteed to be called before the derived class
constructor is called.

In old Python, where instead of __init__ there is a convention to have
a method init which is explicitly called by the caller at construction
time (e.g. x = Window().init('testWindow')) it is the responsibility
of the derived init method to also call the base class init method
(and so on recursively).

First I thought I could improve the situation, by walking the
inheritance tree at creation time ald call all __init__ methods that I
found, in a bottom-up order. But then I realized that I had the same
problem as C++: how to pass each __init__ method its rightful
arguments? In C++ this is solved with special syntax that is only
required if the base constructors need any arguments, but that's
beyond the capabilities of the Python interpreter because it's
impossible to tell how many arguments a function without actually
calling it.

There are several ways out.

One, only call the derived class' __init__ method and hope that it
will call the base class' __init__ method(s). Pro: simple to
imeplement. Con: no real guarantee that a base class' __init__ is
called.

Two, pass the same arguments to all __init__ methods. Pro: still
easy to implement, plus guarantees call to base class' __init__ is
called. Con: sometimes the derived class needs extra arguments, but
adding them to its __init__ method will break the derived class'
__init__ method, so kludges would be necessary.

I presonally think solution One isn't so bad, especially since one can
expect a little extra care from a (derived) class implementer. (And
Python's type checking isn't really strong enough to prevent major
screw-ups anyway.) I also think the problem of solution Two is a real
problem and I don't really see how to solve it.

Anybody have a different opinion or a clever idea? Please speak up!

--Guido van Rossum, CWI, Amsterdam <Guido.van.Rossum@cwi.nl>