Unification of Methods and Functions

David MacQuigg dmq at gain.com
Tue May 25 17:50:18 EDT 2004


On Tue, 25 May 2004 07:17:35 -0600, "Dave Brueck"
<dave at pythonapocrypha.com> wrote:

>David MacQuigg wrote:
>> >> Still this is like saying names that start with the letter 'q' are way
>> >> less common than all other names, so it is OK if we have a special
>> >> form for functions with such names.
>> >
>> >Not at all - that's a flawed analogy because variable names can be pretty
>> >arbitrary and interchangable. The different types of function calls, method
>> >invocations, whatever, are neither arbitrary nor interchangable.
>>
>> Here is a better analogy than my "no-q" functions.  I will use the
>> term "global method" to mean any method containing a global variable.
>> We now have "normal methods", "static methods", "global methods", and
>> a few others.  There is no difference in the calling sequence or the
>> header line between a global method and a normal method.  Yet we don't
>> seem to have any need for a statement like
>> myMethod = globalmethod(myMethod)
>
>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.

>> I'm new to Python and object-oriented programming.  I make no claim of
>> language expertise or vast programming experience.
>
>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.

>> offering a perspective on Python from a technical professional
>> (circuit design engineer) who intends to use it as the basis for a new
>> design platform, and intends to recommend it to students and other
>> technical professionsls who could benefit greatly, but don't have time
>> to learn the language as well as they should.
>
>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.

>> >> What can you do in the current syntax that can't be done more easily in
>the
>> >proposed syntax?
>> >
>> >Understand my code 6 months from now. Modify the code with less risk.
>> >Understand the level of intent in someone else's code I'm using.
>>
>> OK, here is what I can extract from all this:  Having a separate
>> syntax for static methods is beneficial because it tells the
>> programmer at a glance that he can call a method from a class without
>> having an instance of that class at hand.
>
>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.

>> >another thread I suggested you take the time to learn what the 2 or 3 most
>> >common uses are for each of the features that will be affected, and show
>both
>> >the implementation and use in current Python and after your proposed
>changes.
>> >Not only will doing this give a clear example to everyone, it'll also show
>that
>> >you are at least aware of how the different function/method forms are used
>> >today in _real programs_ and not contrived examples - after re-reading some
>of
>> >your comments I have my doubts.
>>
>> I have shown the 4 function/method forms I'm aware of, and how to
>> translate them to a simpler syntax, in Appendix 1 of Prototypes.doc at
>> http://ece.arizona.edu/~edatools/Python  Have you read that?
>
>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".

>> I'm also continually adding new examples under the Examples and
>> Exercises link on that same page.  Many of these are contributed by
>> readers of this thread, including some who would rather not post here.
>> (Gentle Request: A little less intolerance from some others on this
>> thread might encourage more contributions from people they really need
>> to hear from.)
>
>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.

>> As for a real program, it will be a few months before I have anything
>> sizable.  I showed you the statefile example (in response to your
>> request), but you seemed to be insulted, like you thought I was
>> talking down to you, or something.
>
>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.

>Best of luck,
>Dave

You too.  And again, thanks for the careful review.

-- Dave M




More information about the Python-list mailing list