Unification of Methods and Functions

James Moughan moughanj at tcd.ie
Thu May 6 11:37:50 EDT 2004


> 
> The statement about global variables is the only thing that surprises
> me.  

You mentioned them in your first post in the thread, which gave me the
impression I expressed there; my bad, if that's not what you intended.

>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 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.  """
>

The changes would go beyond a simple change of syntax; it would break
the python functional object model, e.g. as you couldn't write a
global function and assign it to a class at runtime.  (I'm not saying
this is a good thing to do :) I'm  saying that this is not a trivial
matter of syntax.)
 
> 
> 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 believe a good working introduction could be done in 10, at most. 
OOP is not complex.  It's even simple enough for managers to (think
they) understand, which leads the slightly bizzare state of
programming today.

> 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.

They are already called like normal functions, though. You can
copy-paste a method as a global function and it will still work.  Your
syntax introduces a special case which makes them distinct, by use of
a specific method-only dot notation.

> 
> ---------------------------
> 
> 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".  

There are static methods in Python? :)  In my coding the major reason
for static methods is for data encapsulation for singleton-style
elements.  Python has no data encapsulation worth anything, so static
methods don't do much that's useful.

> 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 am not copy-pasting the whole thing, but I think this demonstrates
the functionality you want.  It ain't pretty, but I'll discuss that in
a second.

class static:
    def __init__(self, fun):
        self.__call__ = fun

class Mammal:

    numMammals = 0

    def __init__(self):
        Mammal.numMammals += 1

    def show():
        print "Inventory:"
        print " Mammals:", Mammal.numMammals

    show = static(show)

class Feline(Mammal):

    numFelines = 0

    def __init__(self):
        Feline.numFelines += 1
        Mammal.__init__(self)


    def show():
        Mammal.show()
        print " Felines:", Feline.numFelines

    show = static(show)


m = Mammal()
f = Feline()
print Mammal.numMammals, Feline.numFelines, '\n'

Feline.show()


I must note that Animals_2 is a total abuse of OOP techniques.  You
continuously define classes to do the same thing, repeat the same code
in each, then give them slightly different names.

Also, your show method is IMO more than dubious.  show does not
logically belong to Feline.  As a result you are using a class to
display data about other classes to which it is not connected.  This
is not OOP.

If I were teaching someone and they produced this structure then I'd
go over the rationale with them and try to figure out where they went
wrong in their planning of the program, and maybe go back and tutor
them on the basic ideas of OOP.  I would not change the language to
make it easier to do in future.  :)



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



More information about the Python-list mailing list