Dan Perl said:
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.
I may not have enough experience with beginners, I guess -- my wife,
Anna, does have it, and I hope she sees this tidbit and shares that
experience with us. In my limited experience with beginners, in a huge
variety of programming languages and other technologies, they make every
possible mistake and many that are patently impossible too; and if you
try to design your technology to be foolproof, you're wasting your time,
because fools are _extremely_ ingenious. I prefer simplicity and
transparency over desperate attempts to safe fools from their
foolishness -- the smaller, simpler and more transparent a language or
other technology is, the earlier beginners cease to be beginners and
stop making most of their earlier, incredible mistakes.
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__.
Yes, because immutable attributes cannot be mutated -- only by rebinding
that name will anything change, and name rebinding never affects the
object that name previously referred to. But mutable attributes can be
mutated, indeed that's the whole point of having them, rather than just
having their names rebound to refer to other objects. I know you want
some kind of automatic copy of (some?) class attributes to instance
attributes, but I think you just haven't thought clearly enough about
the issues involved, even something as trivial as whether the copy
should be shallow or deep -- the difference will be enormous.
I'm leaving the rest of your reply out, but thanks for the suggestion of a
metaclass, I'll look into it.
You're welcome.
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.
OK.
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
Sure! If they devoted their energy to understanding things in depth and
complete detail, rather than campaigning to change something because
they don't understand that something well enough yet, their adjustment
would be less difficult and we'd all be happier, of course. But human
nature will always make some people perceive that requiring THEM, their
precious and unique SELVES!, to change (their habits, their minds, etc)
is absurd, while it's obviously all the rest of the universe that has to
change to accomodate their tastes and preferences (that may be a
disaster for millions of existing users, but hey, none of those users is
THEM, so they're obviously not very important). They don't generally
phrase things that way (too politically incorrect) and more often than
not they rationalize even to themselves the changes as being good for
mankind, but, really, they're generally just sticking up for their
existing attachments, habits, and worldviews. I'm quite prone to doing
it myself unless I keep up a substantial guard against my own laziness
-- so I try to avoid suggesting any changes in something complex, if I
possibly can avoid that, until and unless I convince myself that I have
a thorough, complete understanding of that something, of the reason for
being and consequences of what I'm thinking of changing, and of the
impact and consequences of what I'd like to change it into.
'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).
It frightens me to consider that Python might one day get designs
decisions made, not because GvR sees them as useful in themselves and
consistent with Python's overall workings, but to "accomodate" people
who are not (yet) familiar with Python. Fortunately I can generally
dispell the fear and calm down, but please don't ask me to consider such
horrid scenarios, they can do nothing but frighten me uselessly.
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).
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.
I don't think you need to worry about this!-)
Alex