473,416 Members | 1,734 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

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

initializing mutable class attributes

There is something with initializing mutable class attributes that I am
struggling with. I'll use an example to explain:
class Father:
attr1=None # this is OK
attr2=[ ] # this is wrong
def foo(self, data):
self.attr1=data
self.attr2.append(data)
The initialization of attr1 is obviously OK, all instances of Father
redefine it in the method foo. But the initialization of attr2 is wrong
because all the instances of Father end up sharing the same value. Maybe
that is desired sometimes, but usually it is just a bug.

So the only solution I see to this is to initialize attr2 in __init__:
class Father:
attr1=None
def __init__(self):
self.attr2=[ ]

This is already awkward because there is such a difference between attr1 and
attr2. But moreover, I think this forces subclasses of Father to do
something like this:
class Child (Father):
def __init__(self):
Father.__init__(self)
self.attr3=[ ]

I find this even more awkward because many people will forget to do it.
Clearly, this is then a more general issue with __init__, but I think it is
accentuated by the fact that you HAVE TO HAVE __init__ in order to
initialize attributes that are mutable.

Is there something I don't know here and there is a better way to do this in
Python? I would like to get a better solution or otherwise start a
discussion.
Jul 18 '05 #1
50 6273
That's the way it is supposed to work. Instance attributes have to be
initialized via self.foo=..., usually in __init__() which in turn is
*STRONGLY* advised to class its parents __init__() - or you create
instance attributes 'on-the-fly' when they are used for the first time
(useful technique for mixin classes without constructor). Class
attributes are initialized once for the class and are shared between
instances.
"self.attr1=data" in Father.foo() doesn't "override" the Father.attr1
attribute you defined before. It creates an instance attribute that
shadows Father.attr1!
Both attribute assignments in Father are OK - if you treat them as class
attributes. They won't become instance attributes by hidden magic.

Dan Perl wrote:
There is something with initializing mutable class attributes that I am
struggling with. I'll use an example to explain:
class Father:
attr1=None # this is OK
attr2=[ ] # this is wrong
def foo(self, data):
self.attr1=data
self.attr2.append(data)
The initialization of attr1 is obviously OK, all instances of Father
redefine it in the method foo. But the initialization of attr2 is wrong
because all the instances of Father end up sharing the same value. Maybe
that is desired sometimes, but usually it is just a bug.

So the only solution I see to this is to initialize attr2 in __init__:
class Father:
attr1=None
def __init__(self):
self.attr2=[ ]

This is already awkward because there is such a difference between attr1 and
attr2. But moreover, I think this forces subclasses of Father to do
something like this:
class Child (Father):
def __init__(self):
Father.__init__(self)
self.attr3=[ ]

I find this even more awkward because many people will forget to do it.
Clearly, this is then a more general issue with __init__, but I think it is
accentuated by the fact that you HAVE TO HAVE __init__ in order to
initialize attributes that are mutable.

Is there something I don't know here and there is a better way to do this in
Python? I would like to get a better solution or otherwise start a
discussion.


Jul 18 '05 #2
Dan Perl <dp***@rogers.com> wrote:
There is something with initializing mutable class attributes that I am
struggling with. I'll use an example to explain:
class Father:
attr1=None # this is OK
attr2=[ ] # this is wrong
def foo(self, data):
self.attr1=data
self.attr2.append(data)
The initialization of attr1 is obviously OK, all instances of Father
redefine it in the method foo. But the initialization of attr2 is wrong
because all the instances of Father end up sharing the same value. Maybe
that is desired sometimes, but usually it is just a bug.
I disagree: good Python programmers often use mutable class attributes,
and use them to good effect. I've done my share of Python teaching,
consulting and mentoring, and I definitely do *not* think this usage "is
desired sometimes but usually it is just a bug".

So the only solution I see to this is to initialize attr2 in __init__:
class Father:
attr1=None
def __init__(self):
self.attr2=[ ]
This is the canonical way, sure.

This is already awkward because there is such a difference between attr1 and
attr2.
One is a class attribute (which nobody forced you to have), the other is
an instance attribute. If you want both to be instance attributes,
initialize both in __init__ -- that's all there is to it. Don't use
class attributes unless there's a reason for them to be class
attributes, that seems like a good and sensible rule of thumb to me.
But moreover, I think this forces subclasses of Father to do
something like this:
class Child (Father):
def __init__(self):
Father.__init__(self)
self.attr3=[ ]
Assuming an instance of Child needs to have both attributes attr2 and
attr3, yes.

I find this even more awkward because many people will forget to do it.
Forget to do what -- call the parent class's __init__? Again, this is
rare -- not as rare as the other "usually just a bug" you opined about,
but not common. A class normally needs __init__ for a large number of
purposes, of course, not just to assign mutable attributes to each
instance, therefore people who learn subclassing do learn to call the
parent class __init__ very early on, to avoid everything breaking.
Clearly, this is then a more general issue with __init__, but I think it is
accentuated by the fact that you HAVE TO HAVE __init__ in order to
initialize attributes that are mutable.
Making __init__ more common means people are more likely to get used to
it, and thus makes the bug of not calling a parent class's __init__
rarer, not "accentuated".

Is there something I don't know here and there is a better way to do this in
Python? I would like to get a better solution or otherwise start a
discussion.


There is no BETTER way, IMHO, than normal Python coding, which I believe
is quite good -- but you appear to disagree, therefore it's hard for me
to gauge what you may consider "better". There is definitely a
DIFFERENT way -- coding a custom metaclass which will tweak the
instantiation of all classes belonging to it, in order to insert some
funky initialization of mutable attributes, and perhaps automate calls
to superclasses' __init__ methods, and so on. Such automation is a
ticklish issue, in the general case, so let's assume initializing
mutable attributes is all we ever want to do. Then, for example...:

import copy
class metaImu(type):
def __call__(cls, *a, **k):
instance = type.__call__(cls, *a, **k)
for sup in cls.mro():
muts = gerattr(sup, '__mutables__', ())
for mutname in muts:
if hasattr(instance, mutname): continue
mutvalue = muts[mutname]
setattr(instance, mutname, copy.copy(mutvalue))
return instance

class Father:
__metaclass__ = metaImu
__mutables__ = dict(attr1=None, attr2={})

class Child(Father):
__mutables__ = dict(attr3=[])

I haven't tested this, but I believe it should behave as you appear to
desire (assuming you want shallow rather than deep copying of the
values, of course: I can't read your mind!). I specifically showed that
you can use __mutables__ also for attributes which are in fact not
mutable, since copy.copy should be innocuous (identity) on those, just
in case you insist on having the same form for all such attributes. I
have also assumed that an instance's __init__ may be allowed to set its
own value for an attribute in __mutables__ and if it does so then that
should be left alone. But of course you can play with all of these
aspects at will. You could even have that __call__ method examine all
attributes defined in the class (or any superclass) and force copies of
them into instance attributes for all whose types are [[whatever
criteria you like...]].
Alex
Jul 18 '05 #3
I will clarify something that was probably not clear enough in my initial
posting. I am interested in instance attributes, but I am using the class
attributes to provide a default, "null", value for the instance attributes.
Yes, the instance attributes only mask the class ones, but a class attribute
and an instance attribute can be used like this:
class WorksForMe:
attr=None # used just as a default value for the instance
attribute self.attr
def foo(self):
self.attr=SomethingUseful( )
def bar(self):
if self.attr:
useIt(self.attr)
else:
ignoreIt(self.attr)
This makes it safe for an instance of WorksForMe to invoke bar( ) even if it
never invoked foo( ).

"Benjamin Niemann" <b.*******@betternet.de> wrote in message
news:cg**********@online.de...
That's the way it is supposed to work. Instance attributes have to be
initialized via self.foo=..., usually in __init__() which in turn is
*STRONGLY* advised to class its parents __init__() - or you create
instance attributes 'on-the-fly' when they are used for the first time
(useful technique for mixin classes without constructor). Class
attributes are initialized once for the class and are shared between
instances.
You are confirming the code I suggested but you don't share my view that
such code is awkward. I think I I was actually conservative calling it
awkward, I would rather call it unsafe. If I were a third-party library
vendor, I would not be comfortable providing a mixin class that forces users
to either invoke the parent's __init__ in their constructors or to
initialize the instance attributes on-the-fly. The latter would even be
against the principles of encapsulation, users should not need to know about
the parent's attributes, especially because they may change in future
releases. Both ways of restricting the use of the mixin class are unsafe
because they are easy to be ignored by users. And it is not only the users'
fault if they do not follow the restrictions, it is also my fault to put
such restrictions in the first place.

I think this points to a weakness in Python as an OO language. I'm not
trying to bash it, but my understanding is that Python is still evolving in
that respect and I think that this should be improved in the future. Then,
on the other hand, maybe I'm the only one feeling this way and there's not
going to be a change.
"self.attr1=data" in Father.foo() doesn't "override" the Father.attr1
attribute you defined before. It creates an instance attribute that
shadows Father.attr1!
Both attribute assignments in Father are OK - if you treat them as class
attributes. They won't become instance attributes by hidden magic.

Dan Perl wrote:
There is something with initializing mutable class attributes that I am
struggling with. I'll use an example to explain:
class Father:
attr1=None # this is OK
attr2=[ ] # this is wrong
def foo(self, data):
self.attr1=data
self.attr2.append(data)
The initialization of attr1 is obviously OK, all instances of Father
redefine it in the method foo. But the initialization of attr2 is wrong
because all the instances of Father end up sharing the same value. Maybe that is desired sometimes, but usually it is just a bug.

So the only solution I see to this is to initialize attr2 in __init__:
class Father:
attr1=None
def __init__(self):
self.attr2=[ ]

This is already awkward because there is such a difference between attr1 and attr2. But moreover, I think this forces subclasses of Father to do
something like this:
class Child (Father):
def __init__(self):
Father.__init__(self)
self.attr3=[ ]

I find this even more awkward because many people will forget to do it.
Clearly, this is then a more general issue with __init__, but I think it is accentuated by the fact that you HAVE TO HAVE __init__ in order to
initialize attributes that are mutable.

Is there something I don't know here and there is a better way to do this in Python? I would like to get a better solution or otherwise start a
discussion.

Jul 18 '05 #4
Dan Perl wrote:
something like this:
class Child (Father):
def __init__(self):
Father.__init__(self)
self.attr3=[ ]

I find this even more awkward because many people will forget to do it.


You have to call base-class-__init__() in every non-trivial inheritance
scheme. Should you forget it, pychecker is always there to remind you

<sloppy-code>
class X:
def __init__(self):
self.x = 2

class Y(X):
pass

class Z(Y):
def __init__(self):
pass
</sloppy-code>

And here's what pychecker says:

$ pychecker t1.py
Processing t1...

Warnings...

t1.py:9: Base class (t1.Y) __init__() not called

Clear enough.

Peter

Jul 18 '05 #5
Dan,

I too use class attributes to assign defaults, but do
it like following:

import copy

class Father:
_attr1default=None
_attr2default=[]

def __init__(self):
self.attr1=self._attr1default
# Get copy of attr2default
self.attr2=list(self._attr2default)

def foo(self, data):
self.attr1=data
self.attr2.append(data)
class Child (Father):
def __init__(self):
Father.__init__(self)
#
# At this point self.attr1 (instance)
# and self.attr2 (instance) hold their defaults
# while _attr1/_attr2default (class) still hold
# their default values for initialization of more
# class instances.
#

HTH,
Larry Bates
Syscon, Inc.
"Dan Perl" <dp***@rogers.com> wrote in message
news:sH*******************@news01.bloor.is.net.cab le.rogers.com...
I will clarify something that was probably not clear enough in my initial
posting. I am interested in instance attributes, but I am using the class
attributes to provide a default, "null", value for the instance attributes. Yes, the instance attributes only mask the class ones, but a class attribute and an instance attribute can be used like this:
class WorksForMe:
attr=None # used just as a default value for the instance
attribute self.attr
def foo(self):
self.attr=SomethingUseful( )
def bar(self):
if self.attr:
useIt(self.attr)
else:
ignoreIt(self.attr)
This makes it safe for an instance of WorksForMe to invoke bar( ) even if it never invoked foo( ).

"Benjamin Niemann" <b.*******@betternet.de> wrote in message
news:cg**********@online.de...
That's the way it is supposed to work. Instance attributes have to be
initialized via self.foo=..., usually in __init__() which in turn is
*STRONGLY* advised to class its parents __init__() - or you create
instance attributes 'on-the-fly' when they are used for the first time
(useful technique for mixin classes without constructor). Class
attributes are initialized once for the class and are shared between
instances.
You are confirming the code I suggested but you don't share my view that
such code is awkward. I think I I was actually conservative calling it
awkward, I would rather call it unsafe. If I were a third-party library
vendor, I would not be comfortable providing a mixin class that forces

users to either invoke the parent's __init__ in their constructors or to
initialize the instance attributes on-the-fly. The latter would even be
against the principles of encapsulation, users should not need to know about the parent's attributes, especially because they may change in future
releases. Both ways of restricting the use of the mixin class are unsafe
because they are easy to be ignored by users. And it is not only the users' fault if they do not follow the restrictions, it is also my fault to put
such restrictions in the first place.

I think this points to a weakness in Python as an OO language. I'm not
trying to bash it, but my understanding is that Python is still evolving in that respect and I think that this should be improved in the future. Then, on the other hand, maybe I'm the only one feeling this way and there's not
going to be a change.
"self.attr1=data" in Father.foo() doesn't "override" the Father.attr1
attribute you defined before. It creates an instance attribute that
shadows Father.attr1!
Both attribute assignments in Father are OK - if you treat them as class
attributes. They won't become instance attributes by hidden magic.

Dan Perl wrote:
There is something with initializing mutable class attributes that I am struggling with. I'll use an example to explain:
class Father:
attr1=None # this is OK
attr2=[ ] # this is wrong
def foo(self, data):
self.attr1=data
self.attr2.append(data)
The initialization of attr1 is obviously OK, all instances of Father
redefine it in the method foo. But the initialization of attr2 is wrong because all the instances of Father end up sharing the same value. Maybe that is desired sometimes, but usually it is just a bug.

So the only solution I see to this is to initialize attr2 in __init__:
class Father:
attr1=None
def __init__(self):
self.attr2=[ ]

This is already awkward because there is such a difference between attr1
and
attr2. But moreover, I think this forces subclasses of Father to do
something like this:
class Child (Father):
def __init__(self):
Father.__init__(self)
self.attr3=[ ]

I find this even more awkward because many people will forget to do
it. Clearly, this is then a more general issue with __init__, but I think
it is accentuated by the fact that you HAVE TO HAVE __init__ in order to
initialize attributes that are mutable.

Is there something I don't know here and there is a better way to do this in Python? I would like to get a better solution or otherwise start a
discussion.


Jul 18 '05 #6

"Alex Martelli" <al*****@yahoo.com> wrote in message
news:1gjc8cs.sqvo1v1fhabdjN%al*****@yahoo.com...
Dan Perl <dp***@rogers.com> wrote:
There is something with initializing mutable class attributes that I am
struggling with. I'll use an example to explain:
class Father:
attr1=None # this is OK
attr2=[ ] # this is wrong
def foo(self, data):
self.attr1=data
self.attr2.append(data)
The initialization of attr1 is obviously OK, all instances of Father
redefine it in the method foo. But the initialization of attr2 is wrong
because all the instances of Father end up sharing the same value. Maybe that is desired sometimes, but usually it is just a bug.


I disagree: good Python programmers often use mutable class attributes,
and use them to good effect. I've done my share of Python teaching,
consulting and mentoring, and I definitely do *not* think this usage "is
desired sometimes but usually it is just a bug".


My mistake. I shouldn't have made that statement. I don't really know
which case happens more often. Having said that, that is probably a mistake
that many beginners make. Okay, I have no real way of knowing that either,
but I think it's a good assumption.
So the only solution I see to this is to initialize attr2 in __init__:
class Father:
attr1=None
def __init__(self):
self.attr2=[ ]


This is the canonical way, sure.

This is already awkward because there is such a difference between attr1 and attr2.


One is a class attribute (which nobody forced you to have), the other is
an instance attribute. If you want both to be instance attributes,
initialize both in __init__ -- that's all there is to it. Don't use
class attributes unless there's a reason for them to be class
attributes, that seems like a good and sensible rule of thumb to me.


I was using the class attribute as a default, "null", value for the instance
attributes. That works just fine for immutable attributes and it allows me
not to implement an __init__.
But moreover, I think this forces subclasses of Father to do
something like this:
class Child (Father):
def __init__(self):
Father.__init__(self)
self.attr3=[ ]


Assuming an instance of Child needs to have both attributes attr2 and
attr3, yes.

I find this even more awkward because many people will forget to do it.


Forget to do what -- call the parent class's __init__? Again, this is
rare -- not as rare as the other "usually just a bug" you opined about,
but not common. A class normally needs __init__ for a large number of
purposes, of course, not just to assign mutable attributes to each
instance, therefore people who learn subclassing do learn to call the
parent class __init__ very early on, to avoid everything breaking.
Clearly, this is then a more general issue with __init__, but I think it is accentuated by the fact that you HAVE TO HAVE __init__ in order to
initialize attributes that are mutable.


Making __init__ more common means people are more likely to get used to
it, and thus makes the bug of not calling a parent class's __init__
rarer, not "accentuated".


I'm leaving the rest of your reply out, but thanks for the suggestion of a
metaclass, I'll look into it.

After seeing a few replies (yours, Benjamin Niemann's and Peter Otten's) to
my initial posting, I think I am getting the picture that there is a
conscious decision to keep the use of __init__ the way it is and just make
people learn it and learn it early enough. That's a valid approach and I'll
accept it.

I can also understand your frustration with people who are new to Python,
like me, coming from a background in other OO languages, who are not yet
comfortable with "the Python way" and feel that there is a "better way" and
who suggest changing Python. But you also have to be reallistic and accept
that there will always be people coming to Python from other languages and
that the adjustment is rather difficult in some areas. You may just say
'Tough!', or you may help them to make that adjustment (I think you are
doing that), or you may even accommodate them (you should at least consider
that).

No one, including you, has given me a reason WHY __init__ is implemented
this way. I am not bashing you for that, I would just still like to hear
that 'WHY'. I'm sure that this implementation has some advantages. But,
coming from a C++ and Java background, where parent default constructors are
automatically invoked (well, not always, and that is something that users
have to learn too), I find that that approach has some clear advantages.

Those are my 2 cents.

Dan
PS: Does my last name attract the wrong kind of attention from people in
this newsgroup? It's really my name, it's not fake, BTW.
Jul 18 '05 #7
Larry,

I don't think it is very different from what I suggested. You still
implement an __init__ and you initialize the instance attributes there.

Thanks, though. It's a nice trick and it's useful because you have a
default value that can be used also in other places in the code (like
restoring the default). And it's probably a good use of pseudo-private
class attributes.

Dan

"Larry Bates" <lb****@swamisoft.com> wrote in message
news:29********************@comcast.com...
Dan,

I too use class attributes to assign defaults, but do
it like following:

import copy

class Father:
_attr1default=None
_attr2default=[]

def __init__(self):
self.attr1=self._attr1default
# Get copy of attr2default
self.attr2=list(self._attr2default)

def foo(self, data):
self.attr1=data
self.attr2.append(data)
class Child (Father):
def __init__(self):
Father.__init__(self)
#
# At this point self.attr1 (instance)
# and self.attr2 (instance) hold their defaults
# while _attr1/_attr2default (class) still hold
# their default values for initialization of more
# class instances.
#

HTH,
Larry Bates
Syscon, Inc.
"Dan Perl" <dp***@rogers.com> wrote in message
news:sH*******************@news01.bloor.is.net.cab le.rogers.com...
I will clarify something that was probably not clear enough in my initial
posting. I am interested in instance attributes, but I am using the class attributes to provide a default, "null", value for the instance attributes.
Yes, the instance attributes only mask the class ones, but a class

attribute
and an instance attribute can be used like this:
class WorksForMe:
attr=None # used just as a default value for the instance
attribute self.attr
def foo(self):
self.attr=SomethingUseful( )
def bar(self):
if self.attr:
useIt(self.attr)
else:
ignoreIt(self.attr)
This makes it safe for an instance of WorksForMe to invoke bar( ) even if it
never invoked foo( ).

"Benjamin Niemann" <b.*******@betternet.de> wrote in message
news:cg**********@online.de...
That's the way it is supposed to work. Instance attributes have to be
initialized via self.foo=..., usually in __init__() which in turn is
*STRONGLY* advised to class its parents __init__() - or you create
instance attributes 'on-the-fly' when they are used for the first time
(useful technique for mixin classes without constructor). Class
attributes are initialized once for the class and are shared between
instances.
You are confirming the code I suggested but you don't share my view that
such code is awkward. I think I I was actually conservative calling it
awkward, I would rather call it unsafe. If I were a third-party library
vendor, I would not be comfortable providing a mixin class that forces

users
to either invoke the parent's __init__ in their constructors or to
initialize the instance attributes on-the-fly. The latter would even be
against the principles of encapsulation, users should not need to know

about
the parent's attributes, especially because they may change in future
releases. Both ways of restricting the use of the mixin class are

unsafe because they are easy to be ignored by users. And it is not only the

users'
fault if they do not follow the restrictions, it is also my fault to put
such restrictions in the first place.

I think this points to a weakness in Python as an OO language. I'm not
trying to bash it, but my understanding is that Python is still evolving

in
that respect and I think that this should be improved in the future.

Then,
on the other hand, maybe I'm the only one feeling this way and there's not going to be a change.
"self.attr1=data" in Father.foo() doesn't "override" the Father.attr1
attribute you defined before. It creates an instance attribute that
shadows Father.attr1!
Both attribute assignments in Father are OK - if you treat them as class attributes. They won't become instance attributes by hidden magic.

Dan Perl wrote:
> There is something with initializing mutable class attributes that I

am > struggling with. I'll use an example to explain:
> class Father:
> attr1=None # this is OK
> attr2=[ ] # this is wrong
> def foo(self, data):
> self.attr1=data
> self.attr2.append(data)
> The initialization of attr1 is obviously OK, all instances of Father
> redefine it in the method foo. But the initialization of attr2 is wrong > because all the instances of Father end up sharing the same value.

Maybe
> that is desired sometimes, but usually it is just a bug.
>
> So the only solution I see to this is to initialize attr2 in __init__: > class Father:
> attr1=None
> def __init__(self):
> self.attr2=[ ]
>
> This is already awkward because there is such a difference between attr1
and
> attr2. But moreover, I think this forces subclasses of Father to do
> something like this:
> class Child (Father):
> def __init__(self):
> Father.__init__(self)
> self.attr3=[ ]
>
> I find this even more awkward because many people will forget to do

it. > Clearly, this is then a more general issue with __init__, but I

think it
is
> accentuated by the fact that you HAVE TO HAVE __init__ in order to
> initialize attributes that are mutable.
>
> Is there something I don't know here and there is a better way to do

this in
> Python? I would like to get a better solution or otherwise start a
> discussion.



Jul 18 '05 #8
On Mon, 30 Aug 2004 15:39:54 GMT, Dan Perl <dp***@rogers.com> wrote:

"Alex Martelli" <al*****@yahoo.com> wrote in message
news:1gjc8cs.sqvo1v1fhabdjN%al*****@yahoo.com...
> So the only solution I see to this is to initialize attr2 in __init__:
> class Father:
> attr1=None
> def __init__(self):
> self.attr2=[ ]
This is the canonical way, sure.

Snip
After seeing a few replies (yours, Benjamin Niemann's and Peter Otten's) to
my initial posting, I think I am getting the picture that there is a
conscious decision to keep the use of __init__ the way it is and just make
people learn it and learn it early enough. That's a valid approach and I'll
accept it.
Snip
No one, including you, has given me a reason WHY __init__ is implemented
this way. I am not bashing you for that, I would just still like to hear
that 'WHY'. I'm sure that this implementation has some advantages. But, Explicit is better than implicit

import this

Dan
PS: Does my last name attract the wrong kind of attention from people in
this newsgroup? It's really my name, it's not fake, BTW.

My nick littlejohn is the direct translation of my last name and I'm
far from big. So what ? :=)
Jul 18 '05 #9
Thanks, Peter. pychecker detecting the wrong use makes the argument that
there is no excuse for making the mistake of not calling the parent's
__init__ in subclasses. I am regularly using pychecker on my code, but I
never saw that warning because I did use __init__ correctly.

But I did make the mistake once of using a class attribute with an empty
dictionary to initialize an instance attribute just because I was doing the
same thing with immutable attributes. Fortunately, I caught it soon enough
and I will not make that mistake again. But it was kind of an embarrassing
mistake and I learned my lesson only after that.

Dan

"Peter Otten" <__*******@web.de> wrote in message
news:cg*************@news.t-online.com...
You have to call base-class-__init__() in every non-trivial inheritance
scheme. Should you forget it, pychecker is always there to remind you
[....]
And here's what pychecker says:

$ pychecker t1.py
Processing t1...

Warnings...

t1.py:9: Base class (t1.Y) __init__() not called

Clear enough.

Peter

Jul 18 '05 #10
Dan Perl wrote:
After seeing a few replies (yours, Benjamin Niemann's and Peter Otten's) to
my initial posting, I think I am getting the picture that there is a
conscious decision to keep the use of __init__ the way it is and just make
people learn it and learn it early enough.
I'd agree.
That's a valid approach and I'll
accept it.
That's nice :)
No one, including you, has given me a reason WHY __init__ is implemented
this way. I am not bashing you for that, I would just still like to hear
that 'WHY'. I'm sure that this implementation has some advantages. But,
coming from a C++ and Java background, where parent default constructors are
automatically invoked (well, not always, and that is something that users
have to learn too), I find that that approach has some clear advantages.
'Why' is a very subjective question. People from different backgrounds
may accept very different answers for why since it may always be in a
specific context (why this instead of *that*?). The following is my idea
of why:

In Python you either have an __init__ or you don't. There is no 'default
constructor' - or if there is, it does nothing. Since attributes can be
dynamically added to an instance (not just in __init__ but in any
method), it follows that the standard practice is to initialize instance
members in __init__ as it is always called before any other instance
method. Now that there is one way to do a thing, Python avoids the
introduction of another way (unless it is notably more productive). That
would lead to a whole set of questions about 'which way is better?
__init__ or the other way?'.

Btw, now that there are descriptors, you can create descriptors that
initialize instance members with default values when they are accessed.
However, unless there is great advantage in your specific case, it might
be just better to follow standard practice and make it easier for
everyone else reading your code.
Dan
PS: Does my last name attract the wrong kind of attention from people in
this newsgroup?


I don't think so.

--
Shalabh

Jul 18 '05 #11

"Shalabh Chaturvedi" <sh*****@cafepy.com> wrote in message
news:ma**************************************@pyth on.org...
'Why' is a very subjective question. People from different backgrounds
may accept very different answers for why since it may always be in a
specific context (why this instead of *that*?). The following is my idea
of why:

In Python you either have an __init__ or you don't. There is no 'default
constructor' - or if there is, it does nothing. Since attributes can be
dynamically added to an instance (not just in __init__ but in any
method), it follows that the standard practice is to initialize instance
members in __init__ as it is always called before any other instance
method. Now that there is one way to do a thing, Python avoids the
introduction of another way (unless it is notably more productive). That
would lead to a whole set of questions about 'which way is better?
__init__ or the other way?'.
It is a subjective issue indeed. But I'll restrict my question to a simpler
question. By analogy to C++ and Java, why is __init__ not implemented to
automatically invoke the __init__(self) of the parent classes? I'm
beginning to see a reason here, which is that C++ and Java allow you to
overload the constructor and have a default constructor at the same time as
another constructor with arguments. C++ and Java then force you to create a
default constructor for a parent class, even if it's empty, if you create a
non-default constructor for it and you subclass the parent class.

In contrast, Python does not allow method overloading and I'm OK with that.
It's a simplification that allows using Python in ways that are not possible
with C++ and Java. So Python cannot force you to have a 'default' __init__
and allow you to have 'non-default '__init__'s at the same time. I am
answering my own question here, but that's OK and it would not have happened
without this discussion.
Btw, now that there are descriptors, you can create descriptors that
initialize instance members with default values when they are accessed.
However, unless there is great advantage in your specific case, it might
be just better to follow standard practice and make it easier for
everyone else reading your code.


I'll have to look more into descriptors, I haven't used them yet and I see
there are many discussions on the topic in this newsgroup. I found your
"Python Attributes and Methods" page on cafepy.com and I'll take a look
there. Thanks!

Dan
Jul 18 '05 #12
Dan Perl wrote:
"Shalabh Chaturvedi" <sh*****@cafepy.com> wrote
In Python you either have an __init__ or you don't. There is no 'default
constructor' - or if there is, it does nothing. Since attributes can be
dynamically added to an instance (not just in __init__ but in any
method), it follows that the standard practice is to initialize instance
members in __init__ as it is always called before any other instance
method. Now that there is one way to do a thing, Python avoids the
introduction of another way (unless it is notably more productive). That
would lead to a whole set of questions about 'which way is better?
__init__ or the other way?'.

It is a subjective issue indeed. But I'll restrict my question to a simpler
question. By analogy to C++ and Java, why is __init__ not implemented to
automatically invoke the __init__(self) of the parent classes? I'm
beginning to see a reason here, which is that C++ and Java allow you to
overload the constructor and have a default constructor at the same time as
another constructor with arguments. C++ and Java then force you to create a
default constructor for a parent class, even if it's empty, if you create a
non-default constructor for it and you subclass the parent class.

In contrast, Python does not allow method overloading and I'm OK with that.
It's a simplification that allows using Python in ways that are not possible
with C++ and Java. So Python cannot force you to have a 'default' __init__
and allow you to have 'non-default '__init__'s at the same time. I am
answering my own question here, but that's OK and it would not have happened
without this discussion.


Yes, if the parent class __init__ accepts parameters, how can Python
call it automatically? Should it be automatic in some cases and
non-automatic in others? (Answer: no, it's too ambiguous). Also what if
there are multiple parent classes? As the Quixote folks put it, in the
face of ambiguity, refuse the temptation to guess. (Btw, Python's
solution for multiple parent classes completely knocks the socks off C++
[1])

Cheers,
Shalabh

[1] http://www.python.org/2.2.3/descrintro.html#cooperation

Jul 18 '05 #13
In article <ma**************************************@python.o rg>,
Shalabh Chaturvedi <sh*****@cafepy.com> wrote:

In Python you either have an __init__ or you don't. There is no 'default
constructor' - or if there is, it does nothing.


Actually, that's not quite true. Python does indeed have a default
constructor that returns the object. This isn't particularly visible
from classic classes because there's no way to get access to a
constructor. New-style classes make the constructor available through
__new__(). __init__() is an initializer.
--
Aahz (aa**@pythoncraft.com) <*> http://www.pythoncraft.com/

"To me vi is Zen. To use vi is to practice zen. Every command is a
koan. Profound to the user, unintelligible to the uninitiated. You
discover truth everytime you use it." --*****@lion.austin.ibm.com
Jul 18 '05 #14

"Alex Martelli" <al*****@yahoo.com> wrote in message
news:1gje9dn.r6jpetyroi0N%al*****@yahoo.com...
............
No one, including you, has given me a reason WHY __init__ is implemented
this way. I am not bashing you for that, I would just still like to hear that 'WHY'. I'm sure that this implementation has some advantages. But, coming from a C++ and Java background, where parent default constructors are automatically invoked (well, not always, and that is something that users have to learn too), I find that that approach has some clear advantages.


In this like in many other details, Python chooses simplicity and
clarity against automatic, black-magic, "behind the scenes" approaches.
"Explicit is better than implicit" is one part of the Zen of Python that
speaks to this -- at a python interactive prompt do
import this
to read it all. The automatic invocation of default constructors when
they exist, what you have to do instead to get different constructors
for parent classes, etc etc, are all complications. When classes are
designed to execute responsibilities it's not unusual that they can't
really have a useful no-arguments constructor -- and when they don't
have such a constructor, C++'s and Java's rules are nothing BUT overhead
and conceptual complication. In C++ one often works around the burden
of contraints on constructor calls via "two-phase constructors" -- a
default constructor that does not really leave the instance in a usable
state, just to bypass the darn rules you find "have some clear
advantages", and then a normal member function that really does the job
of initialization and has the enormous advantage that YOU decide when
and with what arguments to call it, without all the darn rules in the
way, explicitly. Well, in Python the constructor, __init__, is under
you control in exactly this way -- less complication, more simplicity,
more transparency, fewer rules to learn, and far fewer instances of the
"two-phase constructor" pattern (not zero, mind you -- just 99% fewer).


This is the kind of answer I was hoping for. Actually, I was prepared to
see a suggestion for solving the problem in a different way and there were a
couple of them, even if the people suggesting them were themselves advising
to prefer the original solution.

When learning something, I need to understand the 'WHY' behind a design
decision like that, when clearly there are alternatives. I will not be
satisfied with an explanation of "that's the Python way and you just have to
learn it". The explanation of choosing "explicit" instead of "implicit"
makes sense and helps me in better understanding Python. I have to mention
though that I do not accept "explicit is better than implicit" as an
absolute truth. [That's like when someone told me once with pride: "I
always design bottom-up."] Applying a principle like that CONSISTENTLY in
the design of a language can make a very good language. On the other hand,
I can imagine there can be very good languages, with their own uses and
advantages, if the reverse principle were consistently used.

You may see in another message I posted in this thread that I ended up
giving an answer to my own question (the 'WHY' question). Here is my reason
for that 'WHY'. Python does not have method overloading (and I am ok with
that, because it comes with the dynamic typing), so you cannot have a
default constructor and a non-default one at the same time. C++ and Java
have overloading and then can also mandate a default constructor for a
parent class, even if it's empty because you actually use only a non-default
constructor for that class. Python cannot request that you also implement a
default __init__ when you need a non-default one. There would be the
possibility of adding another special method, but there's already __init__
and __new__, so that would be too confusing.

I don't know whether that was an actual reason for the design even if it is
definitely an obstacle. But the principle of "explicit instead of implicit"
(I'll think of it that way) will help me to understand also other aspects of
Python. And thank you for that.

Dan
Jul 18 '05 #15
Dan Perl <dp***@rogers.com> wrote:
...
In this like in many other details, Python chooses simplicity and
clarity against automatic, black-magic, "behind the scenes" approaches. ...
This is the kind of answer I was hoping for. Actually, I was prepared to
see a suggestion for solving the problem in a different way and there were a
couple of them, even if the people suggesting them were themselves advising
to prefer the original solution.
Glad I was helpful (in both ways).

When learning something, I need to understand the 'WHY' behind a design
decision like that, when clearly there are alternatives. I will not be
I absolutely agree: understanding design rationale is crucial to using
complicated systems optimally.
satisfied with an explanation of "that's the Python way and you just have to
learn it". The explanation of choosing "explicit" instead of "implicit"
makes sense and helps me in better understanding Python. I have to mention
I'm glad to hear this.
though that I do not accept "explicit is better than implicit" as an
absolute truth. [That's like when someone told me once with pride: "I
always design bottom-up."] Applying a principle like that CONSISTENTLY in
the design of a language can make a very good language. On the other hand,
I can imagine there can be very good languages, with their own uses and
advantages, if the reverse principle were consistently used.
Perhaps, but from my experience with languages which consistently try to
double-guess programmer intent and "do what's right" implicitly based on
context, it doesn't work -- I'm thinking of PL/I, C++, Perl. They're
all big languages, so perfect consistency is impossible, of course. But
even small languages grow, if they're successful. Do you have specific
examples in mind of very good languages based on "implicit is better
than explicit"?

You may see in another message I posted in this thread that I ended up
giving an answer to my own question (the 'WHY' question). Here is my reason
for that 'WHY'. Python does not have method overloading (and I am ok with
that, because it comes with the dynamic typing), so you cannot have a
default constructor and a non-default one at the same time. C++ and Java
Not with the same name. You can have all alternative constructors you
want if you give them different names -- that's a popular use of
classmethod (in Python as well as in Smalltalk, though there are
differences between the two, of course). Alternative names are more
powerful than any overloading based on type could possibly be.
Consider:
seq = (1,2), (3,4), (5,6)
dict(seq) {1: 2, 3: 4, 5: 6} dict.fromkeys(seq)

{(1, 2): None, (5, 6): None, (3, 4): None}

Overloading based on type would be powerless here, but classmethod
fromkeys of the dict class is perfectly usable to get a different
alternative constructor.
have overloading and then can also mandate a default constructor for a
parent class, even if it's empty because you actually use only a non-default
constructor for that class. Python cannot request that you also implement a
default __init__ when you need a non-default one. There would be the
possibility of adding another special method, but there's already __init__
and __new__, so that would be too confusing.
Java and C++ _could_ mandate a default ctor, but they don't -- it would
be a very bad design decision for them to do so, and their designers
aren't THAT bad:-). It's perfectly possible to have a class that just
CANNOT be constructed without some specific arguments.

I'm not sure why different names would be confusing any more than
different signatures for the same name. Indeed in practice C++ builds
names from signatures (with some added complications regarding hiding of
names apart from signatures). So I don't think this rationale is a good
one for Python's design choices regarding object creation &
initialization.

I don't know whether that was an actual reason for the design even if it is
definitely an obstacle. But the principle of "explicit instead of implicit"
(I'll think of it that way) will help me to understand also other aspects of
Python. And thank you for that.


You're welcome. But I think the impossibility of having several methods
with the same name, differentiated only by signature, is not the root of
things in this particular case.
Alex
Jul 18 '05 #16

"Alex Martelli" <al*****@yahoo.com> wrote in message
news:1gjfkp7.aepmjg11ubf2rN%al*****@yahoo.com...
...
though that I do not accept "explicit is better than implicit" as an
absolute truth. [That's like when someone told me once with pride: "I
always design bottom-up."] Applying a principle like that CONSISTENTLY in the design of a language can make a very good language. On the other hand, I can imagine there can be very good languages, with their own uses and
advantages, if the reverse principle were consistently used.
Perhaps, but from my experience with languages which consistently try to
double-guess programmer intent and "do what's right" implicitly based on
context, it doesn't work -- I'm thinking of PL/I, C++, Perl. They're
all big languages, so perfect consistency is impossible, of course. But
even small languages grow, if they're successful. Do you have specific
examples in mind of very good languages based on "implicit is better
than explicit"?


No, I do not have an example, but I still stand by my comment. Maybe it's
just impossible to use the principle "implicit is better than explicit"
consistently because you need at least something explicit.
You may see in another message I posted in this thread that I ended up
giving an answer to my own question (the 'WHY' question). Here is my reason for that 'WHY'. Python does not have method overloading (and I am ok with that, because it comes with the dynamic typing), so you cannot have a
default constructor and a non-default one at the same time. C++ and Java
Not with the same name. You can have all alternative constructors you
want if you give them different names -- that's a popular use of
classmethod (in Python as well as in Smalltalk, though there are
differences between the two, of course). Alternative names are more
powerful than any overloading based on type could possibly be.
Consider:


We may have a disagreement in terminology, but I was using "overloading" in
the C++/Java sense, which means strictly samename, different signatures.
have overloading and then can also mandate a default constructor for a
parent class, even if it's empty because you actually use only a non-default constructor for that class. Python cannot request that you also implement a default __init__ when you need a non-default one. There would be the
possibility of adding another special method, but there's already __init__ and __new__, so that would be too confusing.


Java and C++ _could_ mandate a default ctor, but they don't -- it would
be a very bad design decision for them to do so, and their designers
aren't THAT bad:-). It's perfectly possible to have a class that just
CANNOT be constructed without some specific arguments.


Try this C++ code:
#include <iostream>
class Class1 {
public:
Class1(int arg )
{
std::cout << "Class1 Constructor" << std::endl;
}
};
class Class2 : public Class1 {
public:
Class2(int arg)
{
std::cout << "Class2 Constructor" << std::endl;
}
};
int main(int argc, char **argv)
{
Class2 c2 = Class2(9);
}

The compiler (I tried gcc) will give an error that the Class1::CLass1( )
constructor is missing. Without the non-default Class1 constructor, the
compiler would have created a default constructor, IMPLICITLY. Note that
even C++ chooses not to create the implicit, default, constructor anymore if
you have a non-default constructor. You have to do it explicitly, even if
it's an empty one.

Anyway, in C++, if I write a library with a class like Class1, I can create
a default constructor to initialize all the members with default values if
there is no need for non-default values. C++ gives me that possibility. A
user of my library (who will never know me) can use this library and does
not need to know anything about the Class1 constructor. This is consistent
with the principle of encapsulation, so subclasses don't need to know
anything about how the superclass is implemented.

Not in Python. A user of my library has to invoke the parent's class
__init__ in their own __init__. What happens if, in a future release, I get
rid of the __init__ in the parent class? Or the other way around. An early
release does not have a parent __init__, the users don't invoke it because
they can't, and then, in a future release, I add the parent __init__ because
I added some attributes. It breaks all the users' code. This is poor
encapsulation.

I think this IS a case where "implicit is better than explicit".

Dan
Jul 18 '05 #17
On Wed, 01 Sep 2004 14:54:06 GMT, Dan Perl <dp***@rogers.com> wrote:
Not in Python. A user of my library has to invoke the parent's class
__init__ in their own __init__. What happens if, in a future release, I get
rid of the __init__ in the parent class? Or the other way around. An early
release does not have a parent __init__, the users don't invoke it because
they can't, and then, in a future release, I add the parent __init__ because
I added some attributes. It breaks all the users' code. This is poor
encapsulation.


Use 'super()', in that case.

http://www.python.org/dev/doc/devel/...cs.html#l2h-70
Jul 18 '05 #18
"Dan Perl" <dp***@rogers.com> writes:
Not in Python. A user of my library has to invoke the parent's class
__init__ in their own __init__. What happens if, in a future release, I get
rid of the __init__ in the parent class? Or the other way around. An early
release does not have a parent __init__, the users don't invoke it because
they can't, and then, in a future release, I add the parent __init__ because
I added some attributes. It breaks all the users' code. This is poor
encapsulation.

I'm getting in the middle of the discussion so forgive-me if this example
doesn't apply here.

class test(object): .... def test(self):
.... print "Just a test"
.... class derived(test): .... def __init__(self):
.... test.__init__(self)
.... def showit(self):
.... self.test()
.... d = derived()
d.showit() Just a test


There was no "__init__" explicitly defined in 'test'.
Be seeing you,
--
Godoy. <go***@ieee.org>
Jul 18 '05 #19
My mistake. You're right, and it's all because of the inheritance from
'object', which probably defines a default, empty, __init__. I haven't made
a habit of subclassing from 'object' yet and I see that I'll have to do
that. Thanks.

Dan

"Jorge Godoy" <go***@ieee.org> wrote in message
news:m3************@g2ctech.com...
"Dan Perl" <dp***@rogers.com> writes:
Not in Python. A user of my library has to invoke the parent's class
__init__ in their own __init__. What happens if, in a future release, I get
rid of the __init__ in the parent class? Or the other way around. An early release does not have a parent __init__, the users don't invoke it because they can't, and then, in a future release, I add the parent __init__ because I added some attributes. It breaks all the users' code. This is poor
encapsulation.

I'm getting in the middle of the discussion so forgive-me if this example
doesn't apply here.

class test(object): ... def test(self):
... print "Just a test"
... class derived(test): ... def __init__(self):
... test.__init__(self)
... def showit(self):
... self.test()
... d = derived()
d.showit() Just a test


There was no "__init__" explicitly defined in 'test'.
Be seeing you,
--
Godoy. <go***@ieee.org>

Jul 18 '05 #20
Dan Perl wrote:
My mistake. You're right, and it's all because of the inheritance from
'object', which probably defines a default, empty, __init__. I haven't
made a habit of subclassing from 'object' yet and I see that I'll have to
do
that. Thanks.


You can safely remove the object as ancestor - it works with old-style
classes, too.

--
Regards,

Diez B. Roggisch
Jul 18 '05 #21
Sorry, Anthony, but I don't think that is relevant for my example. I wasn't
referring to replacing the superclass with another one, which is where
'super( )' would have been useful because it detects the superclass only at
run-time. I was referring to changing the implementation of the superclass,
in which case 'super( )' doesn't make any difference.

See, however, a posting from Jorge Godoy, where he makes the great point
that the problem is removed by always subclassing the base class from
'object'. So the new-style class mechanism is taking care of this problem.

Dan

"Anthony Baxter" <an***********@gmail.com> wrote in message
news:ma**************************************@pyth on.org...
On Wed, 01 Sep 2004 14:54:06 GMT, Dan Perl <dp***@rogers.com> wrote:
Not in Python. A user of my library has to invoke the parent's class
__init__ in their own __init__. What happens if, in a future release, I get rid of the __init__ in the parent class? Or the other way around. An early release does not have a parent __init__, the users don't invoke it because they can't, and then, in a future release, I add the parent __init__ because I added some attributes. It breaks all the users' code. This is poor
encapsulation.


Use 'super()', in that case.

http://www.python.org/dev/doc/devel/...cs.html#l2h-70

Jul 18 '05 #22
I'm not sure what you mean by removing the object as ancestor, but here is a
modified code similar to Jorge's and it doesn't work:
class test:
pass

class derived(test):
def __init__(self):
test.__init__(self)

d = derived()

The call to test.__init__(self) raises an AttributeError exception.

Dan

"Diez B. Roggisch" <de*********@web.de> wrote in message
news:ch*************@news.t-online.com...
Dan Perl wrote:
My mistake. You're right, and it's all because of the inheritance from
'object', which probably defines a default, empty, __init__. I haven't
made a habit of subclassing from 'object' yet and I see that I'll have to do
that. Thanks.


You can safely remove the object as ancestor - it works with old-style
classes, too.

--
Regards,

Diez B. Roggisch

Jul 18 '05 #23
Dan Perl <dp***@rogers.com> wrote:
...
I can imagine there can be very good languages, with their own uses and
advantages, if the reverse principle were consistently used. ...
even small languages grow, if they're successful. Do you have specific
examples in mind of very good languages based on "implicit is better
than explicit"?
No, I do not have an example, but I still stand by my comment. Maybe it's
just impossible to use the principle "implicit is better than explicit"
consistently because you need at least something explicit.


Well, you can imagine anything, including many impossible things, so I
guess your original comment is impossible to falsify -- but that very
solidity makes it rather weak in information content;-)

that, because it comes with the dynamic typing), so you cannot have a
default constructor and a non-default one at the same time. C++ and
... Not with the same name. You can have all alternative constructors you
want if you give them different names -- that's a popular use of ... We may have a disagreement in terminology, but I was using "overloading" in
the C++/Java sense, which means strictly samename, different signatures.
Nevertheless, the observation "you cannot have a default constructor and
a non-default one at the same time" is not correct. If you want to
insist that the constructors MUST all be named __init__, otherwise
they're not constructors but "methods which construct but we cannot name
constructors because constructors must be named __init__", go ahead, but
then, again, we are at an information-free tautology. My point is: you
can have any number of "methods which construct" (constructants? I think
calling them constructors is more idiomatic English!-), just by choosing
the same number of names, one each. So drawing any conclusion from a
premise that "you cannot have a default constructor and a non-default
one at the same time" is faulty reasoning -- the premise is false (by
any meaningful interpretation of the terms in it) so you can prove
anything from it. You may want to try and correctly deduce something
from the true assertion -- "if you have a default constructor and a
non-default one they must have two different names" -- but I don't think
anything necessarily follows from this one.

Java and C++ _could_ mandate a default ctor, but they don't -- it would
be a very bad design decision for them to do so, and their designers
aren't THAT bad:-). It's perfectly possible to have a class that just
CANNOT be constructed without some specific arguments.


Try this C++ code:
#include <iostream>
class Class1 {
public:
Class1(int arg )
{
std::cout << "Class1 Constructor" << std::endl;
}
};
class Class2 : public Class1 {
public:
Class2(int arg)
{
std::cout << "Class2 Constructor" << std::endl;
}
};
int main(int argc, char **argv)
{
Class2 c2 = Class2(9);
}

The compiler (I tried gcc) will give an error that the Class1::CLass1( )
constructor is missing.


Sure, this C++ code is faulty. The way gcc diagnoses that error is
debatable; I would say the fault is more likely to be a missing
" :Class1(someinteger) " between the "Class2(int arg)" and the following
open-brace. I've made my life for years in a job where one of my main
tasks was helping hundreds of programmers write good C++, I've seen this
error often, and the "solution" of adding to Class1 a constructor
callable without arguments was very rarely the right one; almost
invariably those mandatory arguments in Class1's constructor _WERE_
indeed logically necessary -- the class just could not make instances
with meaningful internal state (meeting not just the class invariants,
but the "business purpose" of the class) without those arguments. The
solution was (if the inheritance between concrete classes just could not
be removed in favour of preferable idioms such as Martin's Dependency
Inversion Principle) to ensure subclasses specified the needed arguments
for their superclasses -- that's exactly what C++'s syntax

Class2(int arg): Class1(someint) { ... }

is _for_. ("two-phase constructor" and other solutions also emerge
here).

In brief: given Class1 as it is, you have to call Class1's constructor
explicitly in Class2's constructor, just like in Python (but with far
less flexibility, because it needs to happen _before_ Class2's
constructor body executes -- whence possible needs for two-phase
constructor and the like).
Without the non-default Class1 constructor, the
compiler would have created a default constructor, IMPLICITLY. Note that
even C++ chooses not to create the implicit, default, constructor anymore if
you have a non-default constructor. You have to do it explicitly, even if
it's an empty one.
Or more likely, you have to call Class1's constructor explicitly from
Class'2 constructor. But sure, C++ does have more implicit, "black
magic" behavior "behind the scenes" than Python in quite a few aspects
(though not an unbounded amount) -- the implicit no-arguments do-nothing
constructor is NOT an example, because the result is exactly the same
you get in Python if you have no __init__ at all.

Anyway, in C++, if I write a library with a class like Class1, I can create
a default constructor to initialize all the members with default values if
there is no need for non-default values. C++ gives me that possibility. A
user of my library (who will never know me) can use this library and does
not need to know anything about the Class1 constructor. This is consistent
with the principle of encapsulation, so subclasses don't need to know
anything about how the superclass is implemented.
Encapsulation does not mean you can use a class without knowing its
public methods (including constructors). In particular, inheritance is
a strong coupling, and the superclass must document if it's meant to be
inherited from, with what constructors, what virtual methods allowable
for override, and so on.
Not in Python. A user of my library has to invoke the parent's class
__init__ in their own __init__. What happens if, in a future release, I get
rid of the __init__ in the parent class? Or the other way around. An early
release does not have a parent __init__, the users don't invoke it because
they can't, and then, in a future release, I add the parent __init__ because
I added some attributes. It breaks all the users' code. This is poor
encapsulation.
What (public or protected, in C++) constructors your class has, and with
what arguments, is part of your class's public interface -- of _course_
it's going to break the code of anybody who uses that interface, if you
change the interface between releases.

This is also true in C++, of course. If you want to follow the popular
convention of making all your classes 'canonic' -- all purvued of
default ctor, copy ctor, virtual dtor, default assignment -- you can,
but if you make that choice and publish it (and you'd better publish it,
otherwise how are users of your library going to take any advantage from
its existence?!) then you need to stick with it forevermore or break
users' code. Similarly, in Python, if you want to guarantee to users
that all your classes have an __init__ which may be called without
arguments, nothing at all stops you from doing that -- and then you need
to stick to that published interface aspect, of course.

There are many ways in Python in which you can guarantee that all your
classes have an __init__ which can be called without arguments. If you
need __init__ to be also callable WITH arguments, then make the
arguments optional and check whether they are there -- or give them all
default values just like you could do in C++ (in C++ the default ctor is
not necessarily one "without arguments" -- it can also have arguments as
long as they all have default values). Or go for clarity and make
__init__ argument-less, using classmethods for all other constructors,
as you'd doubtlessly do in Smalltalk, for example. The real problem is
distorting all of your design to ensure all your classes can have
instances with a sensible initial state when instantiated without
arguments -- I think that's far too heavy a price to pay.

Consider for example a Person class. You know all persons have a SSN
(Social Security Number), so how can you instantiate Person without
making an SSN argument mandatory? Basically only by inventing a weird
state for Person instances which is "not fully initialized yet because
the SSN is not known" -- and then ALL methods which could normally count
on the class invariant "instance has a valid SSN" cannot count on that
class invariant any more, must check and contort everything in sight.
What a horrid way to program. It is quite common to get into this bind
if you adhere to the religion of giving EVERY class a default ctor,
because semantically significant classes as they come from a good design
will OFTEN have aspects that it just makes no business-logic sense to
"default" -- so you end up with flags &c to say "this is a PhoneNumber
class instance but it doesn't actually have a number so you can't use it
yet until it's fully initialized", "this is a MailingAddress class
instance but [ditto]", and so on ad nauseam. No thanks!

I think this IS a case where "implicit is better than explicit".


No way: by implicitly trying to call a parent class's default ctor in
any subclass's ctor, C++ is encouraging you to make default ctors
everywhere, and far too often it's better not to have them. Make ctor
calls explicit and live happily.

I've already explained how you can simulate C++'s behavior, and indeed
get even MORE implicit if you wish, and I think it would be a disaster
to USE such a custom metaclass; but if you're sincere in saying it's
better then you should be KEEN to use it. I'm supposed to do other
things this evening (changing some scripts to generate DocBook rather
than XHTML from some semantic-level markup -- fun, fun, fun...;-) but
maybe I'll find the time to take a break and show you the custom
metaclass you need to perpetrate this horror, since you state it's
"better" than Python's explicitness -- no promises tho...
Alex
Jul 18 '05 #24
In article <8J********************@twister01.bloor.is.net.cab le.rogers.com>,
"Dan Perl" <dp***@rogers.com> wrote:
When learning something, I need to understand the 'WHY' behind a design
decision like that, when clearly there are alternatives. I will not be
satisfied with an explanation of "that's the Python way and you just have to
learn it". The explanation of choosing "explicit" instead of "implicit"
makes sense and helps me in better understanding Python. I have to mention
though that I do not accept "explicit is better than implicit" as an
absolute truth.
That's the "Zen" part. Cf. Neils Bohr's definition of a
Great Truth: a Great Truth is a proposition whose opposite
is also a Great Truth.
. [That's like when someone told me once with pride: "I
always design bottom-up."]
:)
A: I always design bottom-up. This is my latest application.
B: What is it?
A: I don't know.

We know where we stood the ladder, but aside from "up",
we can't say much about where it goes.
[ ... ]
You may see in another message I posted in this thread that I ended up
giving an answer to my own question (the 'WHY' question). Here is my reason
for that 'WHY'. Python does not have method overloading (and I am ok with
that, because it comes with the dynamic typing), so you cannot have a
default constructor and a non-default one at the same time. C++ and Java
have overloading and then can also mandate a default constructor for a
parent class, even if it's empty because you actually use only a non-default
constructor for that class. Python cannot request that you also implement a
default __init__ when you need a non-default one. There would be the
possibility of adding another special method, but there's already __init__
and __new__, so that would be too confusing.


I think the difference between:

class B (A):
def __init__ (self, ...)
.... B related stuff
A.__init__ (self, ...)
class B (A):
def __init__ (self, ...)
A.__init__ (self, ...)
.... B related stuff
class B (A):
def __init__ (self, ...)
.... B related stuff
A.__init__ (self, ...)
.... more B related stuff
shows that it's simplest just to code what you want done..
and that's without looking at multiple inheritance,
or different argument lists between A's and B's __init__.

Regards, Mel.
Jul 18 '05 #25

"Alex Martelli" <al*****@yahoo.com> wrote in message
news:1gjg2g0.1yx50mvx6csq3N%al*****@yahoo.com...
...
Nevertheless, the observation "you cannot have a default constructor and
a non-default one at the same time" is not correct. If you want to
insist that the constructors MUST all be named __init__, otherwise
they're not constructors but "methods which construct but we cannot name
constructors because constructors must be named __init__", go ahead, but
then, again, we are at an information-free tautology. My point is: you
can have any number of "methods which construct" (constructants? I think
calling them constructors is more idiomatic English!-), just by choosing
the same number of names, one each. So drawing any conclusion from a
premise that "you cannot have a default constructor and a non-default
one at the same time" is faulty reasoning -- the premise is false (by
any meaningful interpretation of the terms in it) so you can prove
anything from it. You may want to try and correctly deduce something
from the true assertion -- "if you have a default constructor and a
non-default one they must have two different names" -- but I don't think
anything necessarily follows from this one.
We are arguing terminology. I was strictly referring to __init__, but you
are certainly right that Python 'constructors' are a more loose term.
Sure, this C++ code is faulty. The way gcc diagnoses that error is
debatable; I would say the fault is more likely to be a missing
" :Class1(someinteger) " between the "Class2(int arg)" and the following
open-brace. I've made my life for years in a job where one of my main
tasks was helping hundreds of programmers write good C++, I've seen this
error often, and the "solution" of adding to Class1 a constructor
callable without arguments was very rarely the right one; almost
invariably those mandatory arguments in Class1's constructor _WERE_
indeed logically necessary -- the class just could not make instances
with meaningful internal state (meeting not just the class invariants,
but the "business purpose" of the class) without those arguments. The
solution was (if the inheritance between concrete classes just could not
be removed in favour of preferable idioms such as Martin's Dependency
Inversion Principle) to ensure subclasses specified the needed arguments
for their superclasses -- that's exactly what C++'s syntax

Class2(int arg): Class1(someint) { ... }

is _for_. ("two-phase constructor" and other solutions also emerge
here).

In brief: given Class1 as it is, you have to call Class1's constructor
explicitly in Class2's constructor, just like in Python (but with far
less flexibility, because it needs to happen _before_ Class2's
constructor body executes -- whence possible needs for two-phase
constructor and the like).
.....
Or more likely, you have to call Class1's constructor explicitly from
Class'2 constructor. But sure, C++ does have more implicit, "black
magic" behavior "behind the scenes" than Python in quite a few aspects
(though not an unbounded amount) -- the implicit no-arguments do-nothing
constructor is NOT an example, because the result is exactly the same
you get in Python if you have no __init__ at all.


You're right, in most cases that would be the right use. But my example was
just an example and it was just to enforce the earlier statement of "C++ and
Java have overloading and then can also mandate a default constructor for a
parent class."
I've already explained how you can simulate C++'s behavior, and indeed
get even MORE implicit if you wish, and I think it would be a disaster
to USE such a custom metaclass; but if you're sincere in saying it's
better then you should be KEEN to use it. I'm supposed to do other
things this evening (changing some scripts to generate DocBook rather
than XHTML from some semantic-level markup -- fun, fun, fun...;-) but
maybe I'll find the time to take a break and show you the custom
metaclass you need to perpetrate this horror, since you state it's
"better" than Python's explicitness -- no promises tho...


Thanks, but you don't have to bother. It's not something I need right away.
But I should learn that for myself so I will look at your previous posting
and other documentation that I'll find.

Dan
Jul 18 '05 #26
> I'm not sure what you mean by removing the object as ancestor, but here is
a modified code similar to Jorge's and it doesn't work:
class test:
pass

class derived(test):
def __init__(self):
test.__init__(self)

d = derived()

The call to test.__init__(self) raises an AttributeError exception.


I'm sorry, you're right - I meant to modify the example the way you did, to
check if it works or not. But for some reason I just made it run (which was
more work than expected due to embedded unicode spaces) and then forgot to
actually do what I wanted - remove the (object).

And then it doesn't work, as you correctly observed. Sorry for me beeing
confused.

--
Regards,

Diez B. Roggisch
Jul 18 '05 #27

"Mel Wilson" <mw*****@the-wire.com> wrote in message
news:sweNBls/KX*******@the-wire.com...
In article <8J********************@twister01.bloor.is.net.cab le.rogers.com>, I think the difference between:

class B (A):
def __init__ (self, ...)
... B related stuff
A.__init__ (self, ...)
class B (A):
def __init__ (self, ...)
A.__init__ (self, ...)
... B related stuff
class B (A):
def __init__ (self, ...)
... B related stuff
A.__init__ (self, ...)
... more B related stuff
shows that it's simplest just to code what you want done..
and that's without looking at multiple inheritance,
or different argument lists between A's and B's __init__.


Very good point. I would usually assume that you should initialize the
superclass's attributes first, and then the subclass's. But that may not
always be the intent and I may just be influenced by my background in C++
and Java. And yes, with multiple inheritance, you definitely have to know
what attributes are defined in each superclass and you may have to choose
which __init__'s to use and in what order. It's not that C++ handles
multiple inheritance any better (that's one case where "implicit" can make
things worse). I used to work in a big company where it was actually a rule
not to use C++ multiple inheritance (which makes sense in a way because,
even if you use it correctly, someone else may take over your code later and
may have trouble with it, so a conservative company may not want to take a
risk with that). And Java simply solves the problem by not allowing
multiple inheritance (you can 'implement' several 'interfaces', but you can
'extend' only one 'class').

I guess that in Python, everything being public, you have to think of
attributes as being part of the public interface. So you have to know the
attributes of a superclass in order to inherit from it. After all, it's the
same thing with public data members in C++ and Java. But that's why those
languages recommend to make all data members non-public.

It's interesting to compare languages like that. There is an interesting
book, "An Introduction to Object-Oriented Programming", by Timothy Budd. I
read the 2nd edition, a long time ago. I see there is a 3rd edition now,
published in 2001. It explains OO concepts and compares them over several
languages. A little hard to read sometimes, but still interesting. I see
that even the 3rd edition does not cover Python. Maybe a 4th edition?

Dan
Jul 18 '05 #28
After all this discussion, what do people think about this code?
class test(object):
def __new__(typ):
obj = object.__new__(typ)
obj.attr1 = 666
return obj

class derived(test):
def __init__(self):
self.attr2 = 111

d = derived()
print d.attr1, d.attr2
print isinstance(d, test)

The output:
666 111
True

At least it works. The 'test' superclass defines an instance attribute
attr1 and it initializes it with a default. The 'derived' subclass inherits
the attribute (implicitly, BTW ;-)) and that happens without an __init__ in
the superclass that would have to be invoked in the subclass.

Dan
Jul 18 '05 #29
I found a small hole in the initial code suggestion and I fixed it. Try and
find the difference:
class test(object):
def __new__(typ, *args, **kwargs):
obj = object.__new__(typ)
obj.attr1 = 666
typ.__init__(obj, *args, **kwargs)
return obj

class derived(test):
def __init__(self, arg1, arg2):
self.attr2 = arg1
self.attr3 = arg2

d = derived(111, 222)
print d.attr1, d.attr2
print isinstance(d, test)

So, what do people think about it? Alex, would this be good for a recipe in
the Python Cookbook?

Dan

"Dan Perl" <dp***@rogers.com> wrote in message
news:CZ********************@twister01.bloor.is.net .cable.rogers.com...
After all this discussion, what do people think about this code?
class test(object):
def __new__(typ):
obj = object.__new__(typ)
obj.attr1 = 666
return obj

class derived(test):
def __init__(self):
self.attr2 = 111

d = derived()
print d.attr1, d.attr2
print isinstance(d, test)

The output:
666 111
True

At least it works. The 'test' superclass defines an instance attribute
attr1 and it initializes it with a default. The 'derived' subclass inherits the attribute (implicitly, BTW ;-)) and that happens without an __init__ in the superclass that would have to be invoked in the subclass.

Dan

Jul 18 '05 #30
"Dan Perl" <dp***@rogers.com> writes:

(...)
You're right, in most cases that would be the right use. But my example was
just an example and it was just to enforce the earlier statement of "C++ and
Java have overloading and then can also mandate a default constructor for a
parent class."


This point still confuses me, as does the statement it's supposed to
enforce. Your example failed to compile, and the error happened to
reference a missing default constructor, but how does that equate to
mandating such an implementation?

Since I can correct the problem simply by calling the existing
constructor properly from my subclass, clearly I am not _required_ to
implement a default constructor in the base class (which is how I'd
interpret the word "mandate").

C++ may be making an implicit use of such a constructor as part of its
assumptions (and complaining if it doesn't exist), but unless
implementing such a constructor is the only way to satisfy the
compiler, it's not a mandate or requirement that one be provided.

-- David
Jul 18 '05 #31
"Dan Perl" <dp***@rogers.com> writes:

(...)
Very good point. I would usually assume that you should initialize the
superclass's attributes first, and then the subclass's. But that may not
always be the intent and I may just be influenced by my background in C++
and Java. (...)


I do find it reasonably common (particularly in GUI applications when
I'm subclassing standard GUI objects) to have a subclass that massages
the constructor inputs slightly (perhaps adding different defaults, or
filtering the arguments) before passing them on to the superclass.

In C++ you can sometimes manage this as long as the manipulation is
simple exclusion or addition that can be performed in the
initialization code prior to the start of the subclass constructor,
but that's very limited (and otherwise can end up forcing you into the
2-phase construction model). So I find Python's freedom of
controlling exactly when the superclass is initialized with complete
control over its arguments very liberating.

-- David
Jul 18 '05 #32
"Dan Perl" <dp***@rogers.com> writes:
After all this discussion, what do people think about this code?


On face value, I'd question why you're going through the extra effort.
I may be missing the point in such a small example, but just having an
__init__ in the base class that subclasses are supposed to call seems
simpler.

If you're just trying to find some way to have default attributes that can
be used from subclasses without calling __init__, I'd probably just use
class level definitions. For example:

- - - - - - - - - - - - - - - - - - - - - - - - -
Python 2.3.4 (#53, May 25 2004, 21:17:02) [MSC v.1200 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
class Test(object): .... attr1 = 666
.... class Derived(Test): .... def __init__(self):
.... self.attr2 = 111
.... d = Derived()
print d.attr1, d.attr2 666 111 print isinstance(d, Test) True

- - - - - - - - - - - - - - - - - - - - - - - - -

-- David
Jul 18 '05 #33

"David Bolen" <db**@fitlinxx.com> wrote in message
news:u3***********@fitlinxx.com...
"Dan Perl" <dp***@rogers.com> writes:
After all this discussion, what do people think about this code?
On face value, I'd question why you're going through the extra effort.
I may be missing the point in such a small example, but just having an
__init__ in the base class that subclasses are supposed to call seems
simpler.

If you're just trying to find some way to have default attributes that can
be used from subclasses without calling __init__, I'd probably just use
class level definitions. For example:


That is exactly what I'm trying to do, and in the initial posting of the
thread I was mentioning an initialization exactly like yours, but at the
same time I was pointing out that an initialization like that works only for
immutable attributes and not for mutable attributes, hence the need for the
__init__. Or doing it in __new__ as I showed in the new code.
- - - - - - - - - - - - - - - - - - - - - - - - -
Python 2.3.4 (#53, May 25 2004, 21:17:02) [MSC v.1200 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information.
class Test(object): ... attr1 = 666
... class Derived(Test): ... def __init__(self):
... self.attr2 = 111
... d = Derived()
print d.attr1, d.attr2 666 111 print isinstance(d, Test) True

- - - - - - - - - - - - - - - - - - - - - - - - -

-- David

Jul 18 '05 #34
On Thu, 02 Sep 2004 00:17:22 GMT, "Dan Perl" <dp***@rogers.com> wrote:

"David Bolen" <db**@fitlinxx.com> wrote in message
news:u3***********@fitlinxx.com...
"Dan Perl" <dp***@rogers.com> writes:
> After all this discussion, what do people think about this code?


On face value, I'd question why you're going through the extra effort.
I may be missing the point in such a small example, but just having an
__init__ in the base class that subclasses are supposed to call seems
simpler.

If you're just trying to find some way to have default attributes that can
be used from subclasses without calling __init__, I'd probably just use
class level definitions. For example:


That is exactly what I'm trying to do, and in the initial posting of the
thread I was mentioning an initialization exactly like yours, but at the
same time I was pointing out that an initialization like that works only for
immutable attributes and not for mutable attributes, hence the need for the
__init__. Or doing it in __new__ as I showed in the new code.
- - - - - - - - - - - - - - - - - - - - - - - - -
Python 2.3.4 (#53, May 25 2004, 21:17:02) [MSC v.1200 32 bit (Intel)] on

win32
Type "help", "copyright", "credits" or "license" for more information.
>>> class Test(object):

... attr1 = 666
...
>>> class Derived(Test):

... def __init__(self):
... self.attr2 = 111
...
>>> d = Derived()
>>> print d.attr1, d.attr2

666 111
>>> print isinstance(d, Test)

True
>>>

- - - - - - - - - - - - - - - - - - - - - - - - -

-- David

Here's a way to auto-initialize an instance attribute to a mutable via a class variable
(that happens to be a descriptor ;-)
class C(object): ... class prop(object):
... def __get__(self, inst, cls=None):
... if inst: return inst.__dict__.setdefault('prop',[])
... return self
... def __set__(self, inst, value): inst.__dict__['prop'] = value
... def __delete__(self, inst): del inst.__dict__['prop']
... prop = prop()
... c=C()
vars(c) {} c.prop [] vars(c) {'prop': []} c.prop = 'other'
vars(c) {'prop': 'other'} C.prop <__main__.prop object at 0x00901790> del c.prop
vars(c) {} c.prop = 'not auto initialized'
vars(c) {'prop': 'not auto initialized'} c.prop 'not auto initialized' del c.prop
c.prop []

We can also use it as a base class:
C.prop <__main__.prop object at 0x00901790>
class Derived(C): ... def __init__(self):
... self.attr2 = 111
... d = Derived()
print d.prop, d.attr2 [] 111 print isinstance(d, C) True vars(d) {'attr2': 111, 'prop': []} d.prop []

our descriptor is visible via the derived class too, as you would expect Derived.prop <__main__.prop object at 0x00901790> Derived.prop is C.prop True

and so ... d.prop = 's/b d attribute'
vars(d) {'attr2': 111, 'prop': 's/b d attribute'} d.prop 's/b d attribute' del d.prop
vars(d) {'attr2': 111} d.prop [] vars(d)

{'attr2': 111, 'prop': []}

Any use to you? (disclaimer: not tested beyond what you see here ;-)

Regards,
Bengt Richter
Jul 18 '05 #35
Someone else (Shalabh) suggested descriptors for the same problem but I
didn't get to consider such a solution until now. Your posting gave me a
chance to do that. Thanks. I do think though that it is way too much for
just initializing the attributes without an __init__, especially because I
think now I can do it by overriding __new__.

Dan

"Bengt Richter" <bo**@oz.net> wrote in message
news:ch*************************@theriver.com...
On Thu, 02 Sep 2004 00:17:22 GMT, "Dan Perl" <dp***@rogers.com> wrote:

"David Bolen" <db**@fitlinxx.com> wrote in message
news:u3***********@fitlinxx.com...
"Dan Perl" <dp***@rogers.com> writes:

> After all this discussion, what do people think about this code?

On face value, I'd question why you're going through the extra effort.
I may be missing the point in such a small example, but just having an
__init__ in the base class that subclasses are supposed to call seems
simpler.

If you're just trying to find some way to have default attributes that can be used from subclasses without calling __init__, I'd probably just use
class level definitions. For example:
That is exactly what I'm trying to do, and in the initial posting of the
thread I was mentioning an initialization exactly like yours, but at the
same time I was pointing out that an initialization like that works only for
immutable attributes and not for mutable attributes, hence the need for the__init__. Or doing it in __new__ as I showed in the new code.
- - - - - - - - - - - - - - - - - - - - - - - - -
Python 2.3.4 (#53, May 25 2004, 21:17:02) [MSC v.1200 32 bit (Intel)]
onwin32
Type "help", "copyright", "credits" or "license" for more information.
>>> class Test(object):
... attr1 = 666
...
>>> class Derived(Test):
... def __init__(self):
... self.attr2 = 111
...
>>> d = Derived()
>>> print d.attr1, d.attr2
666 111
>>> print isinstance(d, Test)
True
>>>
- - - - - - - - - - - - - - - - - - - - - - - - -

-- David

Here's a way to auto-initialize an instance attribute to a mutable via a

class variable (that happens to be a descriptor ;-)
>>> class C(object): ... class prop(object):
... def __get__(self, inst, cls=None):
... if inst: return inst.__dict__.setdefault('prop',[])
... return self
... def __set__(self, inst, value): inst.__dict__['prop'] = value
... def __delete__(self, inst): del inst.__dict__['prop']
... prop = prop()
... >>> c=C()
>>> vars(c) {} >>> c.prop [] >>> vars(c) {'prop': []} >>> c.prop = 'other'
>>> vars(c) {'prop': 'other'} >>> C.prop <__main__.prop object at 0x00901790> >>> del c.prop
>>> vars(c) {} >>> c.prop = 'not auto initialized'
>>> vars(c) {'prop': 'not auto initialized'} >>> c.prop 'not auto initialized' >>> del c.prop
>>> c.prop []

We can also use it as a base class:
>>> C.prop <__main__.prop object at 0x00901790> >>>
>>> class Derived(C): ... def __init__(self):
... self.attr2 = 111
... >>> d = Derived()
>>> print d.prop, d.attr2 [] 111 >>> print isinstance(d, C) True >>> vars(d) {'attr2': 111, 'prop': []} >>> d.prop []

our descriptor is visible via the derived class too, as you would expect >>> Derived.prop <__main__.prop object at 0x00901790> >>> Derived.prop is C.prop True

and so ... >>> d.prop = 's/b d attribute'
>>> vars(d) {'attr2': 111, 'prop': 's/b d attribute'} >>> d.prop 's/b d attribute' >>> del d.prop
>>> vars(d) {'attr2': 111} >>> d.prop [] >>> vars(d)

{'attr2': 111, 'prop': []}

Any use to you? (disclaimer: not tested beyond what you see here ;-)

Regards,
Bengt Richter

Jul 18 '05 #36
Dan Perl <dp***@rogers.com> wrote:
My mistake. You're right, and it's all because of the inheritance from
'object', which probably defines a default, empty, __init__. I haven't made
a habit of subclassing from 'object' yet and I see that I'll have to do
that. Thanks.


If you define several parent-less classes in a module, it may be simpler
to place at the module's start the assignment statement:

__metaclass__ = type

This is equivalent to explicitly specifying object as the base class of
any otherwise parent-less class.
Alex
Jul 18 '05 #37
Alex Martelli <al*****@yahoo.com> wrote:
...
Anyway, in C++, if I write a library with a class like Class1, I can create
a default constructor to initialize all the members with default values if
there is no need for non-default values. C++ gives me that possibility. A
user of my library (who will never know me) can use this library and does
not need to know anything about the Class1 constructor. This is consistent
Sure DOES "have to know something about Class1 constructor":
specifically that Class1 has a public default constructor, a crucial
piece of information. How CAN you POSSIBLY assert otherwise?!
with the principle of encapsulation, so subclasses don't need to know
anything about how the superclass is implemented.
Encapsulation does not mean you can use a class without knowing its
public methods (including constructors). In particular, inheritance is
a strong coupling, and the superclass must document if it's meant to be
inherited from, with what constructors, what virtual methods allowable
for override, and so on.


Incidentally, FAR from your assertion that, in C++, "subclasses don't
need to know anything about how the superclass is implemented", reality
is just the other way 'round. Subclasses have to be _intimately
familiar_ with key aspects of superclasses' implementation -- not just
the interface (which fully includes the "little detail" of whether a
class has a default ctor or not!!!), but specifically _implementation_
issues, such as what private member names the superclass uses for its
own implementation purposes. That's because C++ fatally tries to
support encapsulation via _accessibility_, NOT through _visibility_. If
the subclass unwittingly tries using a member name which the superclass
is already using privately, it just won't compile; if the superclass
adds any private names to its implementation from one release to
another, it will "break all user code" which quite correctly tried to
use that name (and previously managed w/o problems!) for one of its
members -- as you say. *THIS* is poor encapsulation (Python's attempt
to solve this issue with __-mangling doesn't work wonders, though it's
[a little] better than nothing -- but this should show that the issue of
coupling between superclass and subclass is far more serious than you
imply by asserting that it's solved by C++'s "implicit" rule that if no
other call to a superclass's ctor appears with a subclass's ctor, this
implies a call to the subclass's default ctor).

I think this IS a case where "implicit is better than explicit".


No way: by implicitly trying to call a parent class's default ctor in

... maybe I'll find the time to take a break and show you the custom
metaclass you need to perpetrate this horror, since you state it's
"better" than Python's explicitness -- no promises tho...


Here it is -- now feel free to damage yourself at will with your
conviction that this (calling superclass ctors) "IS a case" where
implicit is better. I decided I can reuse this as a Cookbook recipe,
after all!-)

As an aside, note that, while Python doesn't _quite_ "give you enough
rope to shoot yourself in the foot" by default, it sure provides
excellent rope-manufacturing facilities, sufficient to riddle both of
your feet with bullets with the addition of *a few lines* of support
code...:

def _no_auto(obj): pass

class metaAutoInit(type):

def __call__(cls, *a, **k):
obj = cls.__new__(cls, *a, **k)
for base in cls.mro():
base.__dict__.get('__auto__', _no_auto)(obj)
cls.__init__(obj, *a, **k)
return obj

You could save a statement if you wished to have __auto__ methods called
after __init__ methods (if any) -- then, rather than the two statements,
one to call __new__ and make the empty obj (before calling __auto__
methods), the other after such calling to do the __init__, you could
make an already-inited obj with "obj=type.__call__(cls, *a, **k)" at the
start. But I suspect one would want the auto-initialization to happen
before the explicit one, if any, so I showed how to do that. Anyway, be
it 8 nonblack lines like here, or 7 otherwise, I hope you agree it's a
_trivially little amount of code_ for this amount of meta-functionality,
and the amount of damage (if I'm right) or benefit (if you're right) it
can bring to your Python usage.

In this recipe, __auto__ methods are called on classes in MRO order,
i.e., leaf first. Don't like that, want reverse-MRO order? Fine,
change the 'for' header to loop on cls.mro()[::-1], or, in Python 2.4,
on the more readable reversed(cls.mro()).

This metaclass is designed to silently tolerate base classes without
__auto__, treating such absence as an indication that a given class
wants no auto-initialization -- I think it's the only sensible choice,
but if you disagree, add to the metaclass a def __new__ where it screams
and shouts if a class belonging to it has no '__auto__' in its class
dictionary, or if that __auto__ has incorrect signature (check the
signature with the functions of standard library module inspect) --
better to do that at class-statement time than every time the class gets
instantiated (unless you suspect the user will delight in silently
deleting __auto__ entries from class objects at runtime, of course...).

Ah, one last note: we have to use base.__dict__ here, not getattr, else
a class without __auto__ might inherit __auto__ from a superclass and
that __auto__ would end up getting executed twice, which is probably not
what one normally wants.

Anyway, here's an example of using this custom metaclass:

if __name__ == '__main__': # just show off a bit...
__metaclass__ = metaAutoInit

class a: pass

class b:
def __auto__(self): self.foo=[]

class c(a):
def __auto__(self): self.bar={}

class d: pass

class e(b, c, d):
def __auto__(self): self.baz=c()

z = e()
print z.__dict__

This emits:

{'bar': {}, 'foo': [], 'baz': <__main__.c object at 0x58350>}
There, happy now? Be as implicit as you desire, as long as I don't ever
have to be the one maintaining that code or consulting about it -- I've
served my term with C++, and finally emerged in the bright and fresh
land of Python, where simplicity, explicitnes, and clarity are VIRTUES.
(My wife agrees to the point that we had the Zen of Python among the
readings at our recent wedding, as I mentioned [with a pointer to the
URLs for our marriage readings & photos] in a recent thread...).
Alex
Jul 18 '05 #38
Dan Perl <dp***@rogers.com> wrote:
I found a small hole in the initial code suggestion and I fixed it. Try and
find the difference:
class test(object):
def __new__(typ, *args, **kwargs):
obj = object.__new__(typ)
obj.attr1 = 666
typ.__init__(obj, *args, **kwargs)
return obj

class derived(test):
def __init__(self, arg1, arg2):
self.attr2 = arg1
self.attr3 = arg2

d = derived(111, 222)
print d.attr1, d.attr2
print isinstance(d, test)

So, what do people think about it? Alex, would this be good for a recipe in
the Python Cookbook?


I might run it side by side with my custom metaclass, sure. I'm not
sure why you're running typ.__init__ from within test.__new__ -- it
seems to me that will result in double-running cases.
Alex
Jul 18 '05 #39
Bengt Richter <bo**@oz.net> wrote:
...
Here's a way to auto-initialize an instance attribute to a mutable via a class variable (that happens to be a descriptor ;-)
>>> class C(object):
... class prop(object):
... def __get__(self, inst, cls=None):
... if inst: return inst.__dict__.setdefault('prop',[])
... return self
... def __set__(self, inst, value): inst.__dict__['prop'] = value
... def __delete__(self, inst): del inst.__dict__['prop']
... prop = prop()
...


I think it's the most elegant approach so far, except I would further
tweak it as follows:

class auto_initialized(object):
def __init__(self, name, callable, *args, **kwds):
self.data = name, callable, args, kwds
def __get__(self, ints, cls=None):
if inst:
name, callable, args, kwds = self.data
self = inst.__dict__[name] = callable(*args, **kwds)
return self

No __set__ and __del__ warranted, I believe. Use would then be, e.g:

class C(object):
prop = auto_initialized('prop', list)

Pity that the name must be specified, but ah well, that's descriptors'
defects -- they don't get reminded about the name upon __get__ etc.
Any use to you? (disclaimer: not tested beyond what you see here ;-)


I could use it in the Cookbook, side by side with Dan's "overloading
__new__" idea and my custom metaclass, as various approaches to solving
a 'problem' (if that be one) of "automatically initializing mutable
instance attributes". It would help if you and/or Dan posted these
recipes to ActiveState's online cookbook ASAP (deadline is Sat Sep 5...)
-- I'm allowed to add recipes that didn't show up on the online
cookbook, but that _is_ discouraged... (and posting the recipes myself
isn't much better, either).
Alex
Jul 18 '05 #40
David Bolen <db**@fitlinxx.com> wrote:
"Dan Perl" <dp***@rogers.com> writes:

(...)
Very good point. I would usually assume that you should initialize the
superclass's attributes first, and then the subclass's. But that may not
always be the intent and I may just be influenced by my background in C++
and Java. (...)


I do find it reasonably common (particularly in GUI applications when
I'm subclassing standard GUI objects) to have a subclass that massages
the constructor inputs slightly (perhaps adding different defaults, or
filtering the arguments) before passing them on to the superclass.

In C++ you can sometimes manage this as long as the manipulation is
simple exclusion or addition that can be performed in the
initialization code prior to the start of the subclass constructor,
but that's very limited (and otherwise can end up forcing you into the
2-phase construction model). So I find Python's freedom of
controlling exactly when the superclass is initialized with complete
control over its arguments very liberating.


Very good explanation of the key reason why in C++ you end up using the
pattern "two phase constructor" far more often than in Python (although
it's not _foreign_ to Python, mind you)...
Alex

Jul 18 '05 #41
"Dan Perl" <dp***@rogers.com> writes:
That is exactly what I'm trying to do, and in the initial posting of the
thread I was mentioning an initialization exactly like yours, but at the
same time I was pointing out that an initialization like that works only for
immutable attributes and not for mutable attributes, hence the need for the
__init__. Or doing it in __new__ as I showed in the new code.


Oh (glancing around with an embarrassed look) - you mean the behavior
that's the topic of this thread (generally easily determined by
reading the subject line to which one is replying)...

:-)

-- David
Jul 18 '05 #42

"Alex Martelli" <al*****@yahoo.com> wrote in message
news:1gjhleb.6l5nbvaf0x06N%al*****@yahoo.com...
Bengt Richter <bo**@oz.net> wrote:
...
I could use it in the Cookbook, side by side with Dan's "overloading
__new__" idea and my custom metaclass, as various approaches to solving
a 'problem' (if that be one) of "automatically initializing mutable
instance attributes". It would help if you and/or Dan posted these
recipes to ActiveState's online cookbook ASAP (deadline is Sat Sep 5...)
-- I'm allowed to add recipes that didn't show up on the online
cookbook, but that _is_ discouraged... (and posting the recipes myself
isn't much better, either).


I already submitted mine. It's recipe #303059, so go to:
http://aspn.activestate.com/ASPN/Coo.../Recipe/303059

You are right in an earlier posting that another call to __init__ in the
__new__ was redundant. It was even a problem when using it in the multiple
inheritance case. I figured out eventually that it's not needed and I got
rid of it.

Dan
Jul 18 '05 #43

"Alex Martelli" <al*****@yahoo.com> wrote in message
news:1gjg9tm.14a3nqg36zs8fN%al*****@yahoo.com...
........
Incidentally, FAR from your assertion that, in C++, "subclasses don't
need to know anything about how the superclass is implemented", reality
is just the other way 'round. Subclasses have to be _intimately
familiar_ with key aspects of superclasses' implementation -- not just
the interface (which fully includes the "little detail" of whether a
class has a default ctor or not!!!), but specifically _implementation_
issues, such as what private member names the superclass uses for its
own implementation purposes. That's because C++ fatally tries to
support encapsulation via _accessibility_, NOT through _visibility_. If
the subclass unwittingly tries using a member name which the superclass
is already using privately, it just won't compile; if the superclass
adds any private names to its implementation from one release to
another, it will "break all user code" which quite correctly tried to
use that name (and previously managed w/o problems!) for one of its
members -- as you say.
No, Alex. Data members in a C++ subclass cannot conflict with data members
in its superclass, public, protected, or private. They are resolved by
their namespaces. See an example:
#include <iostream>

class Class1 {
public:
void setM1(int arg) {m1=arg;}
void getM1( ) {std::cout << "c1m1: " << m1 << std::endl;}
private:
int m1;
};
class Class2 : public Class1 {
public:
void setM1(int c1m1, int c2m1) {Class1::setM1(c1m1); m1=c2m1;}
void getM1( ) {Class1::getM1( ); std::cout << "c2m1: " << m1 <<
std::endl;}
private:
int m1;
};
int main(int argc, char **argv)
{
Class2 c2 = Class2( );
c2.setM1(1, 9);
c2.getM1( );
}
Here it is -- now feel free to damage yourself at will with your
conviction that this (calling superclass ctors) "IS a case" where
implicit is better. I decided I can reuse this as a Cookbook recipe,
after all!-)


I'll look at the metaclass example later. Thanks.

Dan
Jul 18 '05 #44
Dan Perl wrote:
Someone else (Shalabh) suggested descriptors for the same problem but I
didn't get to consider such a solution until now.


This is what I had in mind:

---->8-----
class defaultvalue(object): # this is a descriptor
def __init__(self, name, factory):
self.name = name
self.factory = factory

def __get__(self, obj, cls=None):
if obj is None:
return self

val = self.factory()
setattr(obj, self.name, val)
return val
class C(object):
i = defaultvalue('i',dict)
j = defaultvalue('j',list)

c = C()
print c.i, c.j # prints {} []
---->8-----

Once it has kicked in, it's free of the descriptor overhead. Note you
only need to define defaultvalue once and reuse it everywhere. Also you
can give it a function or lambda like:

k = defaultvalue('k', lambda :[1,2,3])

I still suggest you be a good Pythoneer and use __init__() like everyone
else. It's a useful habit of always calling the base class __init__() at
the top of your __init__(). If you don't develop this habit (or of at
least checking the base for __init__), you will waste debugging cycles
when you use other libraries.

--
Shalabh



Jul 18 '05 #45
I really like this one. I think this 'defaultvalue' class even deserves to
be added as a builtin. It can even be changed to initialize non-empty
sequences. And I haven't tried that yet, but it should be able to
initialize an attribute with any kind of object that can be constructed with
no arguments. Too bad it works only for instance attributes in a class.

I will be a good Pythoneer/Pythonista and I will invoke parent __init__'s
whenever using a library. My concern was not as a library user, but as a
library developer. In which case I don't like the idea of relying on users
to be good Python coders.

Dan

"Shalabh Chaturvedi" <sh*****@cafepy.com> wrote in message
news:ma**************************************@pyth on.org...
Dan Perl wrote:
Someone else (Shalabh) suggested descriptors for the same problem but I
didn't get to consider such a solution until now.


This is what I had in mind:

---->8-----
class defaultvalue(object): # this is a descriptor
def __init__(self, name, factory):
self.name = name
self.factory = factory

def __get__(self, obj, cls=None):
if obj is None:
return self

val = self.factory()
setattr(obj, self.name, val)
return val
class C(object):
i = defaultvalue('i',dict)
j = defaultvalue('j',list)

c = C()
print c.i, c.j # prints {} []
---->8-----

Once it has kicked in, it's free of the descriptor overhead. Note you
only need to define defaultvalue once and reuse it everywhere. Also you
can give it a function or lambda like:

k = defaultvalue('k', lambda :[1,2,3])

I still suggest you be a good Pythoneer and use __init__() like everyone
else. It's a useful habit of always calling the base class __init__() at
the top of your __init__(). If you don't develop this habit (or of at
least checking the base for __init__), you will waste debugging cycles
when you use other libraries.

--
Shalabh


Jul 18 '05 #46
Dan Perl wrote:
I will be a good Pythoneer/Pythonista and I will invoke parent __init__'s
whenever using a library. My concern was not as a library user, but as a
library developer. In which case I don't like the idea of relying on users
to be good Python coders.


Don't worry about that - just send them to c.l.py and here we'll badger
them till they succumb and promise to call their parent __init__s
properly <wink>.

Seriously though, I think it's part of Python ideology to trust the
programmer a little more. Notice no private or protected members.
Keeping things explicit and not implicit such as in this case trains
users very quickly. They'll remember to call the parent __init__, or
figure out very quickly when it doesn't work (hopefully with useful
error messages). If things were happening behind the scenes, users will
have a hard time finding out what's going on when it does not work as
expected. Or if they are power users and want to tweak something,
they'll may have to burrow around quite a bit.

That said, in cases it may actually be useful to do certain things
automatically. After all, making life easier for the user is certainly a
good thing. IMO, it's important to accomodate needs of all kinds of
users, but not their fancies. From what I've seen, that seems to be the
way Python itself is developed.

Just my $0.02.

Cheers,
Shalabh

Jul 18 '05 #47
"Shalabh Chaturvedi" <sh*****@cafepy.com> wrote in message
news:ma**************************************@pyth on.org...
.........
Seriously though, I think it's part of Python ideology to trust the
programmer a little more. Notice no private or protected members.
Keeping things explicit and not implicit such as in this case trains
users very quickly. They'll remember to call the parent __init__, or
figure out very quickly when it doesn't work (hopefully with useful
error messages). If things were happening behind the scenes, users will
have a hard time finding out what's going on when it does not work as
expected. Or if they are power users and want to tweak something,
they'll may have to burrow around quite a bit.

That said, in cases it may actually be useful to do certain things
automatically. After all, making life easier for the user is certainly a
good thing. IMO, it's important to accomodate needs of all kinds of
users, but not their fancies. From what I've seen, that seems to be the
way Python itself is developed.


I think that what you're saying and what other people have been saying is
that this is an idiom and it's better to follow idioms in a language because
it helps people understand your code. I agree with that and I guess I will
end up following this idiom. In the end, it's a choice between coding for
the beginners or coding for the experienced. In general, that's not an
obvious choice, but this seems to be quite a common idiom, so the ratio of
beginners who don't know it to people who do know it should be small.

Dan
Jul 18 '05 #48
Dan Perl <dp***@rogers.com> wrote:
"Alex Martelli" <al*****@yahoo.com> wrote in message
news:1gjg9tm.14a3nqg36zs8fN%al*****@yahoo.com...
........
Incidentally, FAR from your assertion that, in C++, "subclasses don't
need to know anything about how the superclass is implemented", reality
is just the other way 'round. Subclasses have to be _intimately
familiar_ with key aspects of superclasses' implementation -- not just
... No, Alex. Data members in a C++ subclass cannot conflict with data members
in its superclass, public, protected, or private. They are resolved by


Sorry, I didn't explain clearly the breakage example -- try this one,
which is as tiny as I can make it:

#include "Base.h"

int foo = 23;
class Derived: public Base {
public:
Derived() { foo = 45; }
};

Is this code correct? Sure, it compiles and runs perfectly using Base
version 12.3. Then Base comes out with version 12.4 and this does not
compile any more. Why? Because the new version of Base has added a
private member named foo.

Admittedly it breaks at compile-time, which is a bit better than
breaking at unittest-time as it would if Base had grown a _public_
member named foo (as the global foo doesn't get updated any more but
rather the per-instance one does). But the point is: coupling between
superclasses and subclasses is STRONG. To code a subclass, you can't
ignore what the superclass is doing, including some implementation
aspects -- much less of course ignore aspects of the superclass's public
interface, as you erroneously claimed.
Alex
Jul 18 '05 #49
Dan Perl <dp***@rogers.com> wrote:
I really like this one. I think this 'defaultvalue' class even deserves to
be added as a builtin. It can even be changed to initialize non-empty
sequences. And I haven't tried that yet, but it should be able to
initialize an attribute with any kind of object that can be constructed with
no arguments. Too bad it works only for instance attributes in a class.
As I posted on the other subthread, you can perfectly well use arguments
in the call, too -- just add *args and **kwds to the descriptor's
__init__ and use them when you later call the factory. This is an
important patter in Python: whenever you design a callable X which
accepts a callable Y as an argument, consider adding *args and **kwds to
X's signature, stashing them away together with Y, and passing them back
into Y when the time comes to call it. This can save users of X writing
lambdas or def functions which have no reason to exist except fixing
such parameters.


I will be a good Pythoneer/Pythonista and I will invoke parent __init__'s
whenever using a library. My concern was not as a library user, but as a
library developer. In which case I don't like the idea of relying on users
to be good Python coders.


If they don't follow good, normal coding practices there is really
little you can do to save them from themselves. Surely nothing worth
distorting all OO design to ensure every class can be meaningfully
initialized without parameters, as I explained in another part of this
thread.
Alex
Jul 18 '05 #50

This thread has been closed and replies have been disabled. Please start a new discussion.

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.