Unification of Methods and Functions

David MacQuigg dmq at gain.com
Sun May 23 08:04:36 EDT 2004


On Sat, 22 May 2004 14:56:29 -0600, "Dave Brueck"
<dave at pythonapocrypha.com> wrote:

>David MacQuigg wrote:
>> >But the above explanation misses one very important point: one is used 99.9%
>of
>> >the time, the other 0.1% of the time, if that. Mentioning them side by side
>> >like you do implies that they are both equially common, which is not
>remotely
>> >the case.
>>
>> I can't comment on the usage statistics you cite, but it seems to me
>> that unbound methods are more important than these statistics would
>> imply.
>
>All I'm saying is that for most programs, the bound method form is way, way,
>way more commonly used than is the unbound calling form.

I would agree if you cut out two of the "ways" in this sentence. :>)
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.  To take this analogy a step
further, I would say that the "no-q" programmers have somehow gotten
used to this restriction, and work around it without even thinking,
while new users find it annoying to have to go back and fix a few
functions because they didn't remember the "no-q" rule.

>> They are necessary to make the language complete, so you can
>> do things that would otherwise require creating an artificial instance
>> just to call a method.
>
>I don't disagree that they are necessary to make the language complete, but
>over and over again you have posted examples of the form "here's a bound method
>example, here's an unbound method example. They're different". Yes, they're
>different, but presenting them that way makes it sound like you normally have
>an equal mix of bound and unbound method calls, and that the difference is so
>subtle that confusion abounds. Neither is true in practice.

I've never stated or implied that unbound methods are as common as
bound methods.  Nor would I say that confusion abounds.  The different
calling sequences are just an unnecessary complexity that trips up
some new users, especially those that don't have experience in some
other OOP language.

>> >>  I know this is not terribly
>> >> difficult to understand -- one is a bound method, the other unbound.
>> >> Still it is a problem for beginners, and it leads to unecessary
>> >> complexities like static methods.
>> >
>> >I don't see how this is at all related to static methods. A method is some
>> >piece of functionality that is specific to a particular class. If you have
>some
>> >function already lying around, why would you want it as a method, much less
>a
>> >static method? (I can think of a couple of rather contrived examples, but
>> >nothing compelling or common in a normal application - help me out here)
>>
>> Here is an example from our CDP ( Circuit Design Platform ):
>>
>> class Bag:
>>     def __init__(self, **kwargs):
>>         self.__dict__.update(kwargs)
>>
>>     def load(infile):
>>         strng = infile.read()
>>         exec( 'bag = Bag(\n' + strng + ')' )
>>         return bag
>>     load = staticmethod(load)
>>
>> We need to load a "statefile" with a deeply nested hierarchy of
>> parameters, which will then be represented by a "Bag" of parameters at
>> each level of the hierarchy.  The load method needs to be called
>> before any Bag exists, so we add the magic "staticmethod" line, and
>> don't worry about 'self'.  Sure, we could move the load function
>> outside of the Bag class, but that would disrupt the natural structure
>> of the program.  The load function is unique to Bags, and it belongs
>> in the Bag class.
>
><sigh> I know what static methods are _for_, but I don't see what is
>necessarily complex about them, nor how your proposed unification would help -
>in fact, ISTM that it would make it much more confusing because both the
>implementor and caller of the code would never be quite sure if the method was
>a static one or not, and that's something that needs to be known by both
>parties.

I think you have not understood the proposal.  It is *not* necessary
in the new syntax to know the difference between a static and
non-static method.  There *is* no difference.  A "static method" (a
function without instance variables) simply ignores __self__.

>Perhaps we both dislike the current staticmethod syntax of Python, but IMO
>making a static method look the same as a non-static method seems like a very
>wrong thing to do. They are quite different in purpose and construction, so to
>me it doesn't make sense that they should look the same in implementation OR in
>usage. See, to me it makes sense that there's no 'self' in a static method -
>since there's no instance for it to refer to. Likewise, it makes sense to me
>that there _is_ a self in a bound method, else member variable lookup would be
>magical (certainly more magical than the fact that a bound method knows what
>instance it belongs to).

The differences are an artifact of the syntax, not any fundamental
difference in purpose.  Normal methods have a special first argument.
Static methods do not.  That's all there is to it.  That's the way I
think when I write a program, and the way I will minimize the
complexity for my students.  I still don't know what "static" means in
this context, but it doesn't matter.  It's just a wart I need to add
after I've written a method definition, if it happens that the method
needs to be called without 'self'.

If there is were some fundamental purpose to static methods, there
would be something they can do that can't be done with the proposed
simpler syntax?  Can you think of any example?

>> See the thread "classes vs dicts" and the discussion following my post
>> on 5/13 for more on statefiles and Bags. See also
>> http://www.ece.arizona.edu/~edatools/Python/Statefiles for the latest
>> on our solution to the statefile problem (how to handle thousands of
>> deeply-nested setup parameters).
>
>Yes - I suggested the basis for your current solution. :)

And I greatly appreciate that suggestion.  The statefile format is now
readable enough that we will avoid having to write our own parser.  By
the way, I wasn't the only one who missed the obvious solution.  An
experienced Python programmer was going down the wrong path with me.

>> >What kind of an instructor would bring this up in an introductory
>programming
>> >course? If you're short on time, there are oodles and oodles of more
>commonly
>> >used topics to cover.
>>
>> Seems like my challenging statement was misleading.  I have no
>> intention of bringing up strange binding problems in an introductory
>> class.  This was a challenge to those who think that Python's binding
>> syntax is simple.
>
>I'd say that first and foremost, it's powerful, and then simple. The example
>IMO shows an abuse of the power without a good reason to do so (my reaction to
>the example as "you're doing something odd for no good reason, and you get odd
>behavior, so what?"). The proposed unification does not seem to take into
>account the benefits of the current design - whether by choice or ignorance I
>don't know.

I may be wrong, but it looks to me like there *are* no benefits of the
current binding syntax over the proposed syntax.

I don't know the reason behind the "Method Binding Confusion" example,
so I would hesitate to tell someone they don't need to do that.  I
assume it was distilled from a much larger program.  It does look
simple enough that I can imagine someone stumbling upon it in the
course of writing an ordinary program.  In any case, the proposed
syntax can do this without any special effort.

What are the benefits of the current design?  What can you do in the
current syntax that can't be done more easily in the proposed syntax?
Show me some code, and I will show you the equivalent in "Python 3".

>> Have you read the proposal at
>> http://www.ece.arizona.edu/~edatools/Python ??
>
>Yep.
>
>> When you say the distinction between methods and functions makes
>> sense, I assume you mean it has some value to the user.  I would like
>> to hear more about this, because I am assuming just the opposite.
>
>Yes it has some value, but more than that: it fits the brain quite well. IMO it
>adheres to the principle of least surprise, 

The Principle of Least Surprise has always been one of my favorites.
It's a shame this principle offers us so little guidance in resolving
a simple issue like this unification question.  It seems to be leading
us in opposite directions.  I think the difference may be in our
backgrounds.  You seem quite comfortable with Java, so I would guess
these different method forms fit with what you have learned there.

I'm coming at it from a different direction -- no CIS background at
all.  I see more beauty, more simplicity, and less surprise in having
just one form of function/method -- unless there is something these
various method forms can do, that I can't do with a simpler syntax,
then I would change my mind, and *highlight* the differences with
keywords like "staticmethod" and "lambda".  With the new syntax, I
wouldn't even use the word "method".

>if you are really thinking about
>what is going on (and this is why I haven't found it to be a problem for
>newbies, because they usually _aren't_ that interested in precisely what is
>going on). And if you're not really thinking about what is going on, it places
>a pretty minimal burden on you - there's only a handful of rules a blissfully
>ignorant programmer needs to adhere to, and that's pretty amazing. But once you
>do understand what is going on, then you can do some pretty powerful things
>that you can't do in e.g. Java (at least not directly and not without a lot of
>work).

I need to feel like I understand what is going on.  I'm not
comfortable with a bunch of arbitrary rules, especially if I
frequently run into cases where forgetting the rules can cause a
problem.  With the proposed syntax, I understand binding completely.
I don't even see any wierd little edge cases, like the example from
the "binding confusion" thread.  In that example, it should not matter
if we are calling a normal function, a built-in function, a normal
method, or a static method.  If the function contains instance
variables ( with a leading dot ), it will look for __self__.  If that
variable is not set, you will get an exception.  That's all there is
to binding.  It doesn't even matter if the function is defined inside
a class, or at the module level.  That choice can be determined by
whatever is the best organization of the program.

>> >Most importantly, I've yet to see it cause any real or lasting problems for
>> >beginners - either (1) nobody cares unless you point it out and make an
>issue
>> >out of it, or (2) they ask, you take 30 seconds to explain it, and they say,
>> >"oh, ok" and move on. Occasionally someone particularly bright (and/or with
>> >experience in certain other languages) will really grasp the 'why' behind
>the
>> >difference, and you'll see the light go on as they begin to understand the
>> >power available to them.
>>
>> I think there is a tendency to assume that whatever you have learned
>> is just the way things have to be.
>
>Maybe, but I'm not arguing that the way things are is the way things have to
>be - I'm arguing that (1) the current way is better than all other proposals to
>date and (2) the specific proposal you've put forward introduces more problems
>than it solves and possibly results in a less powerful language (but I'm not
>sure because I haven't seen examples of how all calling use cases would be
>affected).

I need specific examples of problems introduced by the new syntax, or
of something the old syntax can do better.  We can argue general
principles forever, but one good example will settle this question.

Some of the highly-touted benefits of Prothon, I have concluded are
bunk, and I have eliminated them from my proposal.  The total
elimination of all class-like behavior (getting rid of the "two-tier"
class/instance object model) is a case in point.  In most programs,
two tiers are very useful.  Nobody has even offered a use-case for the
'one-tier" object model of Prothon.  As far as I can tell, none of the
"one-tier" advocates have even looked at Michele Simionato's
implementation of prototypes in Python. (comp.lang.python 4/28/04).

In spite of the bunk, we should not dismiss all the ideas in Prothon.
In my opinion, this unification of methods and functions is the one
gem we can distill from the mess.  We can learn a lot by looking at
how languages designed *after* Python have tried to improve on it.

>> The best introductory text on Python is Mark Lutz' Learning Python,
>> 2nd ed.  He takes 96 pages to cover OOP, and he doesn't waste time on
>> unnecessary topics like metaclasses.  I believe an improvement in
>> Python's syntax could make it possible to cut the number of pages in
>> half, and still reach the same level of proficiency in solving real-world
>problems
>
>But has Mark told you that his goal was brevity? I bet you could cut the pages
>in half without ANY changes to the language, not because he did a poor job (he
>obviously didn't) but because you have different goals in mind.

I assume his goal, like mine, is to teach basic Python with the
minimum time and effort.  Brevity is not a goal in itself.  There is
an optimum number of pages to explain a given set of topics, and I
think Learning Python is pretty close to that optimum.  The reduction
in pages has to come from a reduction in the number of topics.

>> Why is it we can see there is clutter in Perl, but we can't see it in Python?
>
>Nobody is taking that stance, as far as I can tell.

Nobody seems to understand that lambda functions, static methods, etc.
are clutter.

-- Dave




More information about the Python-list mailing list