Unification of Methods and Functions

David MacQuigg dmq at gain.com
Wed May 5 19:17:55 EDT 2004


This is exactly the kind of feedback I'm looking for.  Thank you for
taking the time to recall your experiences in learning Python.

On 5 May 2004 09:17:25 -0700, moughanj at tcd.ie (James Moughan) wrote:
> David MacQuigg wrote:
>< The concept of using a
>> global variable __self__ is no surprise at all.  The only thing new in
>> a class, compared to a module, is the instance variables, and they can
>> be explained in one paragraph.  All methods look just like normal
>> functions.  There is no need to explain "static methods" or any other
>> form of method.  In fact, I use the term "function" rather than
>> "method" to emphasize the similarity.
>> 
>> I'm especially interested in feedback from users who are now learning
>> or have recently learned Python.  
>
>I'd fit there - I've been learning Pyhton for a few weeks, though it's
>now my main language.
>
>The first time I saw the 'self' syntax in Python I recoiled slightly,
>I'll admit, and I took, oooh,  a few tens of minutes to get used to
>including it.  But then I've been programming in Java since 'the
>beginning' so loosing the long habits from that may have slowed me
>down. :)
>
>IMO the current syntax is very, very clear and makes it *easier* to
>understand OOP than any other syntax which I've seen.  If you
>understand functions then you understand arguments; it's obvious how
>that function would work if it weren't bound to a class, and it's a
>simple leap to see the effects of placing a function into a class.
>
>Also, it illuminates your programming in other languages.  Once I saw
>the Pythonic methods, it immediately occured to me how to do OOP in a
>non-OOP language like C.
>
>Overall IMO this particular syntax is one of the things which makes
>Python ideal for teaching OOP.  It's definitely better than waffling
>about global variables which change depending on where you are in the
>code.  I think if I heard that from a lecturer then I'd switch off
>like a light.

The statement about global variables is the only thing that surprises
me.  Have you read the explanations of instance variables at the end
of http://ece.arizona.edu/~edatools/Python/PrototypeSyntax.htm
Does this change your thinking?

Explanation of Instance Variables in Python
-------------------------------------------
"""  Some of the variables inside the functions in a class have a
self. prefix.  This is to distinguish local variables in the function
from "instance variables".  These instance variables will be found
when the function is called, by searching the instance which called
the function.  The way this works is that calling the function from an
instance causes that instance to be passed as the first argument to
the function call.  So if you call cat1.talk(), that is equivalent to
Cat.talk(cat1) If you call cat1.set_vars( "Garfield", "Meow"), that is
equivalent to Cat.set_vars(cat1, "Garfield", "Meow")

The "current instance" argument is automatically inserted as the first
argument, ahead of any other arguments that you may provide in calling
a method that is "bound" to an instance.  Note: The distinction
between instances and classes is important here.  If you call a
function from a class, that function is not bound to any instance, and
you have to supply the instance explicitly in the first argument (
Cat.talk(cat1) )

The variable name self is just a convention.  As long as you put the
same name in the first argument as in the body of the definition, it
can be self or s or even _   The single underscore is handy if you
want to maximally suppress clutter.  """

Explanation of Simplified Instance Variables
--------------------------------------------
""" Some of the variables inside the functions in a prototype have a
leading dot.  This is to distinguish local variables in the function
from "instance variables".  When a function is called from an instance
( cat1.talk() ) a special global variable __self__ is automatically
assigned to that instance ( __self__ = cat1 )  Then when the function
needs an instance variable ( .sound ) it uses __self__ just as if you
had typed it in front of the dot ( __self__.sound )  The leading dot
is just an abbreviation to avoid typing __self__ everywhere.  """

(  For more discussion of this topic see the thread "Explanation of
Instance Variables in Python", comp.lang.python, 4/28/04. )

>Python is a very deep language, but the complexity hits you so late,
>and it's so comprehensible in terms of what's gone before that there's
>no pain involved.  ( esp. contrasted with something like C++ where I
>had to set up rigorous empirical tests to work out what the heck the
>basic structures of the laguage were doing...)

Python is clearly superior to C++ and Java for what I need ( teaching
EE students and professional engineers ).  Still, it isn't perfect.  I
believe a good presentation of OOP could be done in 50 pages ( about
half of what is now in Learning Python, 2nd ed.)  I've written an
explanation of everything basic in the proposed syntax, including
bound and unbound methods, in 7 pages.  ( pages 2-8 of
http://ece.arizona.edu/~edatools/Python/Prototypes.doc )  It still
needs examples and exercises, but I probably won't continue if there
is not more interest from the Python community.

The key to this simplification is not having to discuss static methods
or any other method form.  All methods are called just like normal
functions, which the students already understand at this point in the
course.

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

I think the learning process you describe above is quite common.  I
went through the same initial steps.  At first I was puzzled by the
strange 'self' first argument, and annoyed at typing 'self' in so many
places.  Then I understood the magic first argument, and got used to
the extra typing.  It did not occur to me that there was some
unnecessary complexity yet to come.  I had not yet seen how 'self' is
handled in Ruby and in Prothon.  I did not learn about static methods
and other forms until much later, and 'lambdas' were something weird
related to "lambda calculus".  Part of my problem was that the
pressures from my regular job did not allow much time to be studying
Python - exactly the kind of pressure that my students and clients are
now facing.

I did not start using static methods until recently.  I just did what
the textbook examples showed, and steered around the need for these
"advanced" method forms.  A problem with this strategy is that the
need for static methods arises quite naturally in some fairly simple
programs. ( See the Animals_2.py example in the Prototypes document
above.)  This is not like metaclasses, which really can be avoided by
beginners.  It is more like telling new users they can't use the
letters q and w in their variable names.  Sure, you can work around
it, but it constrains what you would naturally do just sitting down to
write your first Python programs.

The second problem with the "avoidance/denial" strategy is that it
involves moving the troublesome functions outside of the class
definition.  This results in a less-than-optimal structure for your
program.  Look at the show() methods in Animals_2.py  They must be
callable without any specific instance.  Moving them outside the
appropriate classes is not good programming.  When you want to change
a class later, you will need to remember to look in some other place
for any "static methods" associated with the class.

If you could do me one more favor, please take a look at the
Animals_2.py example starting on page 7 of the Prototypes document at
http://ece.arizona.edu/~edatools/Python  Can you write this in Python?
Give it a try, and let me know if you had any difficulties.  Were
there any parts you had to stop and think, or look up in a manual?

I appreciate the effort it takes to thoroughly investigate this issue.

-- Dave




More information about the Python-list mailing list