472,142 Members | 1,039 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,142 software developers and data experts.

OOP / language design question

I was wondering, why you always have to remember to call bases'
constructors explicitly from the derived class constructor? Why hasn't
this been enforced by the language?

Apr 25 '06 #1
31 1558
cc*******@gmail.com:
I was wondering, why you always have to remember to call bases'
constructors explicitly from the derived class constructor? Why hasn't
this been enforced by the language?


Probably because the language doesn't know whether the subclass wants to
override its base class's constructor, or enhance it.

--
René Pijlman
Apr 25 '06 #2
cc*******@gmail.com wrote:
I was wondering, why you always have to remember to call bases'
constructors explicitly from the derived class constructor? Why hasn't
this been enforced by the language?


I have another question for you: why does JAVA enforce that a constructor of
a base-class must be called prior to everything else in the derived class's
constructor? No way to do some computing for parameters that I want to pass
to the parent constructor...
Besides, this automatically base-constructor-calling only happens for the
most trivial of cases - the no-argument-constructors.

Regards,

Diez
Apr 25 '06 #3
Am Dienstag 25 April 2006 12:34 schrieb cc*******@gmail.com:
I was wondering, why you always have to remember to call bases'
constructors explicitly from the derived class constructor? Why hasn't
this been enforced by the language?


Because sometimes you don't want to call the base classes constructors? The
Python zen says: "Better explicit than implicit," and in this case it hits
the nail on the head. Better to see right away what your code does (the
explicit call to the base class), than to have to work around calling a bases
constructor if you don't want to call it.

--- Heiko.
Apr 25 '06 #4
Diez B. Roggisch wrote:
I have another question for you: why does JAVA enforce that a constructor of
a base-class must be called prior to everything else in the derived class's
constructor? Well, I can imagine it's done to make sure that the base(s) are
properly constructed. Sound s sensible to me.
No way to do some computing for parameters that I want to pass
to the parent constructor...
Try this:

Derived::Dreived() : Base(calcParam1(), calcParam2())
....
Besides, this automatically base-constructor-calling only happens for the
most trivial of cases - the no-argument-constructors.


Well, the language can at least ensure that theconstructor is called -
i.e. either call it automatically if it can be called without
parameters, or fail with error.

Apr 25 '06 #5

Heiko Wundram wrote:
Because sometimes you don't want to call the base classes constructors? Sounds strange to me at the moment, but I'll try to adjust to this
thought.
Python zen says: "Better explicit than implicit," and in this case it hits
the nail on the head. Better to see right away what your code does (the
explicit call to the base class), than to have to work around calling a bases
constructor if you don't want to call it.

Thanks, that explains it somehow - at least, it's consistent with
explicit "self".
I think I'll need some shift in thinking after C++.

Apr 25 '06 #6
cc*******@gmail.com:
I think I'll need some shift in thinking after C++.


+1 qotw

--
René Pijlman
Apr 25 '06 #7
> Well, I can imagine it's done to make sure that the base(s) are
properly constructed. Sound s sensible to me.
It often is - there are popular examples in python where missing a
constructor will cause a program to fail spectacular. But is it _always_ a
sensible thing to do? No. If you only want some code inherited, but set up
the required constraints to do so yourself. Such things can't be expressed
in C++/JAVA, but that doesn't mean they aren't the sensible solution in
some cases.
No way to do some computing for parameters that I want to pass
to the parent constructor...


Try this:

Derived::Dreived() : Base(calcParam1(), calcParam2())
...


Oh, I know about that. however, there are limits to this. For example, you
can't do anything that depends on constructors called before in case of
multiple inheritance. And you are forced to create a static method to do
so, which can be viewed as ugly as well.
Well, the language can at least ensure that theconstructor is called -
i.e. either call it automatically if it can be called without
parameters, or fail with error.


Yes, it can do that because of static typing - in fact it will fail on a lot
more of occasions with a compilation error.

The question here is if you are willing to trade freedom of expressiveness
against the proposed security of static typing. I found that I favor the
former and can live without the latter.

Diez
Apr 25 '06 #8
cc*******@gmail.com wrote:
Heiko Wundram wrote:
Because sometimes you don't want to call the base classes constructors?

Sounds strange to me at the moment, but I'll try to adjust to this
thought.


It makes sense in more static languages such as C++. The base class is
initialised by the constructor, so you have to do everything possible to
ensure that initialisation is done before you actually try to use any part
of the base class. Weird things can still happen in C++ if you start
calling methods too soon (e.g. to calculate some of the base constructor's
parameters): you can find uninitialised member variables and you might not
get exactly the virtual methods you expected.

Python is more laid back about these things. The object itself already
exists when __init__ is first called. It already has a type, which
(unlike C++) isn't going to change part way through. All that is missing
are a few attributes, and if you try to access them too soon you'll get an
exception rather than a random value.

It makes sense therefore to give the programmer the scope to override the
expected sequence of initialisation for those rare cases where it actually
matters. The programmer also gets enough scope to shoot themselves in the
foot, but Python programmers are expected to be intelligent enough not to
do that accidentally.

Usually though, if a subclass doesn't immediately call the base class
constructors as the first thing it does in __init__ it indicates poor code
and should be refactored.

BTW, the same arguments apply to destructors: if you have a __del__ method
and need to call the base __del__ methods you have to do that manually as
well.
Apr 25 '06 #9
Duncan Booth wrote:
(snip)
Usually though, if a subclass doesn't immediately call the base class
constructors as the first thing it does in __init__ it indicates poor code
and should be refactored.


Not necessarily. It's a common case to have some computations to do/some
attributes to set in the derived class's __init__ before calling the
superclass's.

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Apr 25 '06 #10
cc*******@gmail.com wrote:
I was wondering, why you always have to remember to call bases'
constructors


<pedantic>
s/constructors/__init__/

the __init__() method is *not* the constructor. Object's instanciation
is a two-stage process: __new__() is called first, then __init__().
</pedantic>

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Apr 25 '06 #11
cc*******@gmail.com wrote:
Heiko Wundram wrote:
Because sometimes you don't want to call the base classes constructors?

Sounds strange to me at the moment, but I'll try to adjust to this
thought.


In Java and C++, classes have private members that can only be accessed
by the class itself (and, in C++, friends). In those languages, a base
constructor needs to be called to initialize the base class's private
members.

Python has no private members (except for the double underscore
thingies, which aren't that common). Unlike C++ and Java, the derived
class's __init__ can usually initialize all the base class's members,
and it's occasionally useful to do so.

I would agree it's a mistake to not call the base class's __init__
unless you're doing it deliberately. If you want a tool to catch those
mistakes, have a look at pychecker. It can inform you whenever the
base class __init__ is not called.

(However, I totally disagree that it's a good idea to always call it
first, though. I've written base class __init__s that expected the
subclass to provide initialization methods, and some of those methods
needed some subclass members to exist before they were called.)

Apr 25 '06 #12
bruno at modulix wrote:
Duncan Booth wrote:
(snip)
Usually though, if a subclass doesn't immediately call the base class
constructors as the first thing it does in __init__ it indicates poor
code and should be refactored.


Not necessarily. It's a common case to have some computations to
do/some attributes to set in the derived class's __init__ before
calling the superclass's.


I did only say 'usually'. Can you actually think of any good examples where
you have to set a derived attribute before you can call the base class
constructor? I can't, which is why I was a bit vague.

The base class is unlikely to depend on the derived class attributes, and
unless it does there should be no reason which you can't just call the base
__init__ straight away. Perhaps if the base __init__ calls an overridden
method, but at that point it sounds to me like something wants refactoring.

I can think that you might have to do some computations to calculate
parameters for the base __init__, but that is a separate issue.
Apr 25 '06 #13

bruno at modulix wrote:
cc*******@gmail.com wrote:
I was wondering, why you always have to remember to call bases'
constructors


<pedantic>
s/constructors/__init__/

the __init__() method is *not* the constructor. Object's instanciation
is a two-stage process: __new__() is called first, then __init__().
</pedantic>


You know, Python's __init__ has almost the same semantics as C++
constructors (they both initialize something that's already been
allocated in memory, and neither can return a substitute object). I
actually think constructors are misnamed in C++, they should be called
initializers (and destructors finalizers). The only thing is that C++
doesn't always call operator new when constructing objects, whereas
Python always calls __new__, so you can put some initialization in
__new__ if you want.

Other than that I'd say that Python __init__ is analogous to Java and
C++ constructors, but is not a constructor because C++ and Java
constructors are not constructors. :) And Java has pointers, not
references. :)

A-rose-by-any-other-name-ly yr's,

Carl Banks

Apr 25 '06 #14
Carl Banks wrote:
You know, Python's __init__ has almost the same semantics as C++
constructors (they both initialize something that's already been
allocated in memory, and neither can return a substitute object).


There is a significant difference: imagine B is a base type and C a
subclass of B:

When you create an object of type C in Python, while B.__init__ is
executing self is an object of type C (albeit without all the attributes
you expect on your C).

In C++ when the B() constructor is executing the object is an object of
type B. It doesn't become a C object until the C() constructor is
executing.

In other words, the object is constructed in Python before any __init__ is
called, but in C++ it isn't constructed until after all the base class
constructors have returned.
Apr 25 '06 #15
Duncan Booth wrote:
In other words, the object is constructed in Python before any __init__ is
called, but in C++ it isn't constructed until after all the base class
constructors have returned.


That's true. Good point.
Carl Banks

Apr 25 '06 #16
Duncan Booth wrote:
bruno at modulix wrote:

Duncan Booth wrote:
(snip)
Usually though, if a subclass doesn't immediately call the base class
constructors as the first thing it does in __init__ it indicates poor
code and should be refactored.
Not necessarily. It's a common case to have some computations to
do/some attributes to set in the derived class's __init__ before
calling the superclass's.

I did only say 'usually'. Can you actually think of any good examples where
you have to set a derived attribute before you can call the base class
constructor?


class Base(object):
def __init__(self, arg1):
self.attr1 = arg1
self.dothis()

def dothis(self):
return self.attr1

class Derived(Base):
def __init__(self, arg1, arg2=0):
self.attr2 = arg2
Base.__init__(self, arg1)

def dothis(self):
return self.attr1 + self.attr2

(snip)
Perhaps if the base __init__ calls an overridden
method, but at that point it sounds to me like something wants refactoring.
Why so ? This is a well-known pattern (template method). I don't see
what's wrong with it.
I can think that you might have to do some computations to calculate
parameters for the base __init__, but that is a separate issue.

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Apr 25 '06 #17
bruno at modulix wrote:
class Base(object):
def __init__(self, arg1):
self.attr1 = arg1
self.dothis()

def dothis(self):
return self.attr1

class Derived(Base):
def __init__(self, arg1, arg2=0):
self.attr2 = arg2
Base.__init__(self, arg1)

def dothis(self):
return self.attr1 + self.attr2

(snip)
Perhaps if the base __init__ calls an overridden
method, but at that point it sounds to me like something wants
refactoring.


Why so ? This is a well-known pattern (template method). I don't see
what's wrong with it.


Apart from the fact that you can delete the method 'dothis' from both
classes with no effect on the code?

Actually, this is quite an interesting example becaue it wouldn't work in
C++: if you tried the same trick the call to dothis from the base
constructor (even assuming it is virtual) would actually call Base.dothis.

I think you have demonstrated that you can do some things in Python which
you simply cannot do in static languages like C++: assigning to derived
attributes before calling a base initialiser, and calling a virtual method
from a base initialiser. I'm not arguing about that. What I don't have
though is an example of code where doing this would actually be a good
thing.

What I think I'm trying to get at is that I believe that most situations
where someone actually tries to do something in the base initialiser which
requires calling a virtual method are probably also cases where the
initialiser is doing too much: i.e. separating the
construction/initialisation from actually doing something is usually a good
idea.
Apr 25 '06 #18
Duncan Booth a écrit :
bruno at modulix wrote:

class Base(object):
def __init__(self, arg1):
self.attr1 = arg1
self.dothis()

def dothis(self):
return self.attr1

class Derived(Base):
def __init__(self, arg1, arg2=0):
self.attr2 = arg2
Base.__init__(self, arg1)

def dothis(self):
return self.attr1 + self.attr2

(snip)

Perhaps if the base __init__ calls an overridden
method, but at that point it sounds to me like something wants
refactoring.
Why so ? This is a well-known pattern (template method). I don't see
what's wrong with it.

Apart from the fact that you can delete the method 'dothis' from both
classes with no effect on the code?


Mmmm... Oh, I see. Agreed, this is not a very good example.
class Base(object):
def __init__(self, arg1):
self.attr1 = arg1
self.attr42 = self.dothis()


Is that better ?-)

Ok, let's be serious now...
Actually, this is quite an interesting example becaue it wouldn't work in
C++: if you tried the same trick the call to dothis from the base
constructor (even assuming it is virtual) would actually call Base.dothis. I think you have demonstrated that you can do some things in Python which
you simply cannot do in static languages like C++: assigning to derived
attributes before calling a base initialiser, and calling a virtual method
from a base initialiser. I'm not arguing about that. What I don't have
though is an example of code where doing this would actually be a good
thing.
I don't have any concrete example at hand, but I can tell you I've done
such things often enough.
What I think I'm trying to get at is that I believe that most situations
where someone actually tries to do something in the base initialiser which
requires calling a virtual method
I'm afraid I fail to see what's so special about 'virtual' methods - and
FWIW, since all methods in Python are virtual, if you don't want to call
virtual methods in the initializer, you won't get very far !-)
are probably also cases where the
initialiser is doing too much: i.e. separating the
construction/initialisation from actually doing something is usually a good
idea.


What if some of the things one have to do at initialization is also used
elsewhere ? You would not duplicate code, would you ?
Apr 25 '06 #19
Duncan Booth <du**********@invalid.invalid> wrote:
...
Actually, this is quite an interesting example becaue it wouldn't work in
C++: if you tried the same trick the call to dothis from the base
constructor (even assuming it is virtual) would actually call Base.dothis.
Yep.
I think you have demonstrated that you can do some things in Python which
you simply cannot do in static languages like C++: assigning to derived
attributes before calling a base initialiser, and calling a virtual method
from a base initialiser. I'm not arguing about that. What I don't have
though is an example of code where doing this would actually be a good
thing.
A recognized idiom/pattern in C++ or Java is known as "two-phase
construction" (yes, there's a two-phase destruction counterpart): have
minimal, near-empty constructors, then a separate virtual Init method
which does the actual construction work (often with a framework or at
least a factory to ensure that Init gets in fact called).

Each use case of this idiom/pattern relies on virtual methods (most
generally in a Template Method design pattern) at initialization.

E.g.: build a composite window by iteratively building subwindows
(including decorators) as enumerated by a virtual method. Initialize a
database-connection object by delegating some parts (such as connection,
local or over the net, and authentication, etc etc) to virtual methods.
And so on, and so forth.

What I think I'm trying to get at is that I believe that most situations
where someone actually tries to do something in the base initialiser which
requires calling a virtual method are probably also cases where the
initialiser is doing too much: i.e. separating the
construction/initialisation from actually doing something is usually a good
idea.


But why should that be? Template Method is perhaps the MOST generally
useful design pattern -- why would it be any less useful in
initialization than elsewhere?!
Alex
Apr 26 '06 #20
Alex Martelli wrote:
What I think I'm trying to get at is that I believe that most
situations where someone actually tries to do something in the base
initialiser which requires calling a virtual method are probably also
cases where the initialiser is doing too much: i.e. separating the
construction/initialisation from actually doing something is usually
a good idea.


But why should that be? Template Method is perhaps the MOST generally
useful design pattern -- why would it be any less useful in
initialization than elsewhere?!

Because it is error prone?

Any method which is called from the constructor/initialiser has to operate
correctly on an object which at that point is not fully
constructed/initialised. So instead of having to write a method on a Foo
object, your template method has to operate on a partial Foo. The danger is
that you haven't clearly defined the partial Foo interface sufficiently and
the method tries to use other parts of the object which haven't yet been
set up. That situation gets worse when you have a class hierarchy as the
subclass needs to know that it has to do complete its own initialisation
before constructing the base class instead of afterwards, and if you are
going to document that requirement, why not do it properly and split the
construction in two?

That's why I would go for the 2-phase construction: after the first phase
you have an object which is fully initialised, just not yet
used/connected/running. For example httplib.HTTPConnection does this: you
construct the object with a host and port, but the actual connection is
triggered by a separate object.
I would suggest your example of a database connection belongs in that
category: it should have an initial unconnected idle state and a separate
connection.

I think your example of a composite window building subwindows is the sort
of use case I was asking for: it does sound tempting to construct the
window and all its subwindows together. I'm happy to concede on that one.
Apr 26 '06 #21
Duncan Booth wrote:
Alex Martelli wrote:

What I think I'm trying to get at is that I believe that most
situations where someone actually tries to do something in the base
initialiser which requires calling a virtual method are probably also
cases where the initialiser is doing too much: i.e. separating the
construction/initialisation from actually doing something is usually
a good idea.
But why should that be? Template Method is perhaps the MOST generally
useful design pattern -- why would it be any less useful in
initialization than elsewhere?!


Because it is error prone?


Programming *is* error prone.
Any method which is called from the constructor/initialiser has to operate
correctly
any method has to operate correctly anyway !-)
on an object which at that point is not fully
constructed/initialised.
In Python, when the __init__ method is called, the object is at least
fully constructed.
So instead of having to write a method on a Foo
object, your template method has to operate on a partial Foo. The danger is
that you haven't clearly defined the partial Foo interface sufficiently and
the method tries to use other parts of the object which haven't yet been
set up.
If so, the worse thing that can happen is an exception - and you'll
surely spot the problem really soon.
That situation gets worse when you have a class hierarchy as the
subclass needs to know that it has to do complete its own initialisation
before constructing the base class instead of afterwards, and if you are
going to document that requirement, why not do it properly and split the
construction in two?
It's *already* split : __new__ construct the object, __init__ initialize it.
That's why I would go for the 2-phase construction:
But that's already what you have.
after the first phase
you have an object which is fully initialised, just not yet
used/connected/running. For example httplib.HTTPConnection does this: you
construct the object with a host and port, but the actual connection is
triggered by a separate object.


If you look at file objects, they do try and open the file at init time.
Is a net or db connection that different ?

(snip)

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Apr 26 '06 #22

Duncan Booth wrote:
Alex Martelli wrote:
What I think I'm trying to get at is that I believe that most
situations where someone actually tries to do something in the base
initialiser which requires calling a virtual method are probably also
cases where the initialiser is doing too much: i.e. separating the
construction/initialisation from actually doing something is usually
a good idea.


But why should that be? Template Method is perhaps the MOST generally
useful design pattern -- why would it be any less useful in
initialization than elsewhere?!

Because it is error prone?

Any method which is called from the constructor/initialiser has to operate
correctly on an object which at that point is not fully
constructed/initialised. So instead of having to write a method on a Foo
object, your template method has to operate on a partial Foo. The danger is
that you haven't clearly defined the partial Foo interface sufficiently and
the method tries to use other parts of the object which haven't yet been
set up.


In Python, if you try to use an uninitialized member you get an
AttributeError; I really don't see too much inherent danger here. If
you make a mistake, the language tells you and you fix it. C++ and
Java are worse since accessing uninitialized variables is a silent
mistake, so it makes sense to avoid that kind thing in those languages.

Carl Banks

Apr 26 '06 #23
bruno at modulix wrote:
It's *already* split : __new__ construct the object, __init__
initialize it.
That's why I would go for the 2-phase construction:


But that's already what you have.


Very good point.
after the first phase
you have an object which is fully initialised, just not yet
used/connected/running. For example httplib.HTTPConnection does this:
you construct the object with a host and port, but the actual
connection is triggered by a separate object.


If you look at file objects, they do try and open the file at init
time. Is a net or db connection that different ?


Well, yes, since the whole point is that we are discussing overriding
methods and I bet you haven't subclassed Python file objects recently.

For network or database connections you do want to supply your own
handlers for things like authentication.
Apr 26 '06 #24
Duncan Booth wrote:
bruno at modulix wrote:

It's *already* split : __new__ construct the object, __init__
initialize it.
That's why I would go for the 2-phase construction:


But that's already what you have.


Very good point.

after the first phase
you have an object which is fully initialised, just not yet
used/connected/running. For example httplib.HTTPConnection does this:
you construct the object with a host and port, but the actual
connection is triggered by a separate object.


If you look at file objects, they do try and open the file at init
time. Is a net or db connection that different ?

Well, yes, since the whole point is that we are discussing overriding
methods and I bet you haven't subclassed Python file objects recently.


And you win !-)

Anyway, I didn't suggest that opening a connection to whatever should be
done in the __init__ - I just wanted to point that acquiring a resource
in the initializer (and freeing it in the finalizer) can sometimes be
perfectly sensible.

wrt/ initializer as a template method, I still fail to see why this
should be a problem. The fact that one should avoid doing anything else
than initialization in the initializer is just plain old common sense
IMHO - the use of calls to other methods that can possibly be overriden
in a subclass is orthogonal. And if the guy writing the subclass do
stupid things when overridding these methods, well, too bad for him -
but as the author of the base class, that's definitively not my problem
(given proper documentation of course)

Trying to protect stupid programmers from doing stupid things is a total
waste of time anyway.

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Apr 26 '06 #25
Bruno Desthuilliers said unto the world upon 25/04/06 06:52 PM:
Duncan Booth a écrit :
bruno at modulix wrote:
class Base(object):
def __init__(self, arg1):
self.attr1 = arg1
self.dothis()

def dothis(self):
return self.attr1

class Derived(Base):
def __init__(self, arg1, arg2=0):
self.attr2 = arg2
Base.__init__(self, arg1)

def dothis(self):
return self.attr1 + self.attr2

(snip)

Perhaps if the base __init__ calls an overridden
method, but at that point it sounds to me like something wants
refactoring.

Why so ? This is a well-known pattern (template method). I don't see
what's wrong with it.

Apart from the fact that you can delete the method 'dothis' from both
classes with no effect on the code?

Mmmm... Oh, I see. Agreed, this is not a very good example.


<snip>

This hobbyist isn't seeing Duncan's point. Wouldn't deleting the
dothis method from both classes lead to an AttributeError as
Base.__init__ calls self.dothis()?

Is the point that one could refactor out the self.dothis() from the
__init__? Or something else altogether? (I assume it can't be that
dothis isn't doing real work as it is in the context of a toy example.)

Enlightenment gratefully received.

Best to all,

Brian vdB
Apr 26 '06 #26
Brian van den Broek wrote:
Bruno Desthuilliers said unto the world upon 25/04/06 06:52 PM:
Duncan Booth a écrit :
(snip)
Apart from the fact that you can delete the method 'dothis' from both
classes with no effect on the code?
Mmmm... Oh, I see. Agreed, this is not a very good example.


<snip>

This hobbyist isn't seeing Duncan's point. Wouldn't deleting the dothis
method from both classes lead to an AttributeError as Base.__init__
calls self.dothis()?


Yes, of course. But Duncan (implicitely) meant "deleting the method
*and* the calls to the method".

The point is that dothis() returns a value (that is not used), and
doesn't modify the state of self.

Or at least, this what *I* understood.
Is the point that one could refactor out the self.dothis() from the
__init__? Or something else altogether? (I assume it can't be that
dothis isn't doing real work as it is in the context of a toy example.)


Seems like you are assuming too much !-)
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Apr 26 '06 #27
In article <Xn*************************@127.0.0.1>,
Duncan Booth <du**********@invalid.invalid> wrote:
Carl Banks wrote:
You know, Python's __init__ has almost the same semantics as C++
constructors (they both initialize something that's already been
allocated in memory, and neither can return a substitute object).


There is a significant difference: imagine B is a base type and C a
subclass of B:

When you create an object of type C in Python, while B.__init__ is
executing self is an object of type C (albeit without all the attributes
you expect on your C).

In C++ when the B() constructor is executing the object is an object of
type B. It doesn't become a C object until the C() constructor is
executing.

In other words, the object is constructed in Python before any __init__ is
called, but in C++ it isn't constructed until after all the base class
constructors have returned.


But if "construction" is what a constructor does, then you're wrong.
Apr 27 '06 #28
In article <11**********************@e56g2000cwe.googlegroups .com>,
"Carl Banks" <in**********@aerojockey.com> wrote:
bruno at modulix wrote:
cc*******@gmail.com wrote:
> I was wondering, why you always have to remember to call bases'
> constructors


<pedantic>
s/constructors/__init__/

the __init__() method is *not* the constructor. Object's instanciation
is a two-stage process: __new__() is called first, then __init__().
</pedantic>


You know, Python's __init__ has almost the same semantics as C++
constructors (they both initialize something that's already been
allocated in memory, and neither can return a substitute object). I
actually think constructors are misnamed in C++, they should be called
initializers (and destructors finalizers).


"Constructor" is also the term used for the corresponding method in Java.

Is there any OO language that does not use "constructor" in this sense?
I don't think there is one. This is standard OO terminology.
Apr 27 '06 #29
Lawrence D'Oliveiro wrote:
In other words, the object is constructed in Python before any
__init__ is called, but in C++ it isn't constructed until after all
the base class constructors have returned.


But if "construction" is what a constructor does, then you're wrong.

I may be wrong (my C++ is getting rusty), but my belief is that if you have
a base class B and a derived class D, then until the B() constructor has
returned, the type of the object (as indicated by RTTI or by calling
virtual methods) is a B. It isn't until after the B constructor has
returned that the object is changed into a D.

This is different from Python's behaviour where the object is created as
its final type and then initialised.
Apr 27 '06 #30

Lawrence D'Oliveiro wrote:
In article <11**********************@e56g2000cwe.googlegroups .com>,
"Carl Banks" <in**********@aerojockey.com> wrote:
bruno at modulix wrote:
cc*******@gmail.com wrote:
> I was wondering, why you always have to remember to call bases'
> constructors

<pedantic>
s/constructors/__init__/

the __init__() method is *not* the constructor. Object's instanciation
is a two-stage process: __new__() is called first, then __init__().
</pedantic>


You know, Python's __init__ has almost the same semantics as C++
constructors (they both initialize something that's already been
allocated in memory, and neither can return a substitute object). I
actually think constructors are misnamed in C++, they should be called
initializers (and destructors finalizers).


"Constructor" is also the term used for the corresponding method in Java.

Is there any OO language that does not use "constructor" in this sense?
I don't think there is one. This is standard OO terminology.


Python?

Yeah, I realize it's common terminology, but I just think it's a poor
name. That Python doesn't really call __init__ a constructor is good
(I guess it doesn't really call it anything but __init__), because
constructor would be a bad name for it.
Carl Banks

Apr 27 '06 #31
Lawrence D'Oliveiro wrote:
In article <11**********************@e56g2000cwe.googlegroups .com>,
"Carl Banks" <in**********@aerojockey.com> wrote:

bruno at modulix wrote:
cc*******@gmail.com wrote:

I was wondering, why you always have to remember to call bases'
constructors

<pedantic>
s/constructors/__init__/

the __init__() method is *not* the constructor. Object's instanciation
is a two-stage process: __new__() is called first, then __init__().
</pedantic>
You know, Python's __init__ has almost the same semantics as C++
constructors (they both initialize something that's already been
allocated in memory, and neither can return a substitute object). I
actually think constructors are misnamed in C++, they should be called
initializers (and destructors finalizers).

"Constructor" is also the term used for the corresponding method in Java.

Is there any OO language that does not use "constructor" in this sense?


Smalltalk. Just like Python, it has constructor *and* initializer.
I don't think there is one. This is standard OO terminology.


Being "standard" doesn't imply it's accurate.

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Apr 27 '06 #32

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

35 posts views Thread by John Coleman | last post: by
25 posts views Thread by Dave | last post: by
11 posts views Thread by Bryan | last post: by
669 posts views Thread by Xah Lee | last post: by
11 posts views Thread by Sarath | last post: by
27 posts views Thread by notnorwegian | last post: by
reply views Thread by leo001 | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.