Ugh, I'm sorry but this analogy seems as bad as the no-q analogy. That's like
saying methods that contain for-loops should be declared differently - but in
neither case is the thing that matters to the caller - the interface (both the
explict means by which the function is used as well as the explicit or implicit
contract and purpose of the function) - affected. Let's move on.
OK, but this issue is definitely not settled.
Doesn't it give you pause that many other people, both with and without that
background, have encouraged you to give the current feature set a chance? As
in, use these features for awhile, get some more experience with them, and in
time you'll come to understand the 'why' behind them? Again, I'm not asserting
that the current language is perfect, just that the way things are might have a
purpose and/or the proposal you've come up with has drawbacks worse than what
we already have... If nothing else, waiting until you have a lot of programs
under your belt will let you argue your point from a position of strength.
OK, I will wait until I have earned the right to make such a bold
proposal. If I still feel the same three months from now, I'll post
again, assuming I still have the time and desire to debate the issue.
That is the problem with saying that only experts can propose changes.
Right now the issue is a hot topic for me, because I've just been
through the learning experience. Three months from now, I will
probably feel the same about the technical merits of the proposal, but
won't have the desire to engage in a long debate.
It does disturb me that I am the sole advocate for the proposal on
this thread, but I don't consider this to be a reprentative sample of
users either. I think the whole discussion may be a bit intimidating
for the users I am most concerned about.
I guess the best counter to the argument that "Everybody disagrees
with you, recant!" is -- No, I don't think that the folks who
developed Ruby or Prothon would disagree with me. Python is far from
perfect when people feel the need to develop a whole new language that
does basically the same thing.
Just to head off some flames here -- in spite of the few minor faults
I see in Python, it is by far the best language for me.
Then what you really ought to do is not cover more advanced topics any sooner
than is needed. Really. Nobody taking an intro-to-programming course needs to
learn about e.g. classmethods. They just don't need to. In your course pass out
a link to a web page of advanced reading for those you want to know more, and
leave it at that. Burdening them with tools they won't use anytime soon won't
be doing them a favor. Instead, teach them how to find answers to their
questions, how to experiment, so that _if_ and when they do come across it then
they can go learn it then.
Who said I was going to cover class methods? The three forms I see as
important are bound and unbound methods, and static methods. For the
rest, including lambda functions, I'll have a link to python.org/doc
or a reference to the discussion in Learning Python, 2nd ed.
That's part of it, but there's more - a static method is used in different
scenarios and for different purposes. They generally aren't interchangeable
beasts.
It's these mystical qualities of the "more" part that have me
mystified. Whatever those qualities may be, the same can be done with
the new syntax. That leaves the only difference as what I have stated
above -- the visibility of a static method. There is no other
difference in actual use of the two syntaxes.
Yes, but as I pointed out elsewhere, it may help to write about this in some
other context than your other proposals (the fact that this is buried in
Appendix 1 under a title of "Translating Python Classes to Prototypes" doesn't
lend itself to much reader traffic).
I will soon post to my website translations of the programs I have
received, and any others that someone cares to send me.
But, it's better than nothing, so here goes:
1. Bound methods - the calling appears to be identical in either version, but
one of the real values of the bound method form is being able to call the bound
method _when you don't have the instance variable handy_ (I'm just trying to
point out why it's useful).
In either syntax you don't need the instance handy to call the bound
method. It was bound at the time the bound method was created, and it
stays bound even if the instance is deleted. Bound functions in both
syntaxes are immutable.
Anyway, the fact that the methods don't have a self
variable does make things seem a little magical - with 'self' in the arg list
it makes sense to me how self.foo grabs a variable from the current instance.
Yes, there is some magic in the current implementation in that the self arg
gets passed in, but the alternative is either uglier or more magical, so it
seems like a good compromise between explicitness and practicality.
I see the two ways of passing self as equally magical, and the magic
is *insignificant* in either case. In one case we insert a magic
first argument 'self'. In the other we set a magic global variable
__self__. If I had to chose solely on the basis of minumum magic, I
would go with the global variable, because students already understand
global variables at this point. They also understand function
arguments, but the insertion of an argument is a little startling.
Again, the magic in either case is so small that I would say this is
in the realm of personal preference.
By the way, both Ruby and Prothon have decided *not* to pass 'self' in
the first argument, and they were well aware of Python's convention
when these decisions were made.
2. Unbound methods - the example uses an unbound method to "bypass" a subclass
method - that seems like a really unrealistic example. Inserting the superclass
method into the subclass, but with a different name seems equally odd. Thus,
the whole argument in favor of the "Python 3" version is unappealing. What's
downright frightening, however, is that you can write something like '__self__
= c' and get the same behavior (for many reasons, not the least of which is
that two seemingly unrelated statements are completely linked). Wanting to call
a superclass method with the current instance is a much more likely example,
but with either form of the "Python 3" syntax it's quite unclear that that is
what is happening - because it's indistinguishable from the other calls, it's w
ay less clear what the code is doing. Thus, both newbies and experts alike will
have a more difficult time understanding (and maintaining and modifying) the
code.
I agree the example is unrealistic. Rarely, if ever, will you need to
call an unbound method from the module level, or over-ride the default
binding to __self__. The example merely shows that it can be done, if
you must. I need to show a bunch of simple cases, so people don't
dwell on these extremes. The more common case ( calling an unbound
method from inside another method, keeping the same __self__ as the
bound instance ) looks identical to current Python, except there is no
'self' in the arg list.
3. Static methods - your page doesn't list any examples of calling the
functions, but I assume that in both cases it's Mammal.show(). Not much to be
unified here, although I don't like the fact that the "Python 3" version loses
the information that it is a static method (I don't particularly like the fact
that for the current version the staticmethod call happens after the method
body - I like some of the proposals in the related PEP), but in current Python
you actually have two indicators - there's no 'self' parameter. And again, you
have the same problem in the calling code - it's not clear what is happening,
and yet what is happening is a pretty important piece of info. In the "new"
syntax, the call could be to a static method or to a superclass method, but the
reader of the code is left wondering which one it is.
I wish I could understand why highlighting a method as being a
staticmethod is so important to you. Others have said that
staticmethods are really rare, and could even be deprecated. So if
you really needed to scan a method body, and see if it has any
instance variables, this would be a rare annoyance.
What is the consequence of missing the fact that a method doesn't use
'self'? What if we were to unify the two forms by going the other way
-- All methods use 'self'? If an instance doesn't exist, it is
created, ignored, then deleted.
I know you hate the "globalmethod" analogy, but there is actually
*more* justifation here for having a special form. If you call a
static method from an instance, nothing bad happens. The __self__ is
just ignored. If you miss the fact that a method needs global
variables, all hell could break loose. :>)
4. Class methods - this example just seems broken, but perhaps I'm misreading
it. In the Python 3 version, a string is getting passed in to the class method,
and the prototype of the *string* is then displayed - makes no sense to me. In
any case, class methods are IMO a pretty advanced topic - since a main point of
yours is that you want to make OO more accessible to the lay programmer, I
don't see how class methods would come up in the discussion at all - they'd be
more relevant to a metaclass or descriptor discussion.
Your right. It is broken. I wish I had a "Python 3" interpreter to
check these things. I believe this is the first time anyone has
looked at this section carefully, and I appreciate your effort.
You are also right about classmethods being an advanced topic, and I
won't be covering them in my class. I needed to show this example,
because rare as they are, if there were not an automatic translation
of classmethods to the new syntax, some existing programs would not
survive a migration, and that alone is a cost higher than the value of
any changes I am proposing.
I need to move this appendix out of the introductory chapter and make
it an appendix to the syntax proposal.
The example should have been Mammal.show(tiger), where tiger is an
instance or a class, not a "string".
Equally gentle request: don't be too hasty in assuming that because people
disagree with you, their previous experience has clouded their perceptions or
made them forget what it was like to walk the path you're currently on.
If I have offended anyone with a statement like this, I sincerely
appologize. The intolerance I was talking about was direct personal
attacks, and angry or sarcastic remarks. This group has far less of
it than most other groups I have participated in.
Not at all, just realize how your message sounds on the receiving end (whether
you intended it to come across this way or not): "Even though I haven't really
used these features much, I think they should be changed. Other people say the
features have a purpose, and that the purpose becomes clear over time, but I
disagree." That, in itself, is hard to take too seriously, although I'm
impresed at how many people apparently took the time to think about your
suggestion.
I'm sorry that my "message" comes across as you suggest. I try always
to start with an open mind. If I don't understand the purpose of a
feature, I say "show me". Only after repeated attempts to get
something more concrete, do I tentatively reach a different
conclusion. I'm skeptical, but I think I'm more cautious than most in
not making dogmatic statements without understanding an issue.
I also have no hesitation to acknowledge when I'm wrong. I was
pushing "prototypes" ( as done in Prothon ) until Michele Simionato
showed that they could be done with the existing machinery in Python.
They are still in my proposal, but with a clear statement that they
won't make the next revision unless someone shows that Michele's
"prototype.py" module is missing something important.
On the issue of staticmethods, I use them more freely than most others
on this thread would prefer. I disagree that they have a fundamental
purpose in life, but I respect others' opinions, and I have my
receiver at maximum sensitivity, in case someone were to post an
example that would make me say - Oh cool, now I understand the true
purpose of staticmethods, and the reason they deserve a special
syntax.
You too. And again, thanks for the careful review.
-- Dave M