Migrating to perl?

Martijn Faassen m.faassen at vet.uu.nl
Sat Jan 6 00:29:31 EST 2001


Joel Ricker <joejava at dragonat.net> wrote:
> Martijn Faassen wrote in message <933fa1$j2i$1 at newshost.accu.uu.nl>...
[snip]
> From your examples, Pythons class model is much cleaner.

It definitely looks and feels cleaner to me!

> Also if I understand your example, variables internal to the object are kept
> internal -- they can't be accessed without a proper method.  With perl
> anything goes.  There are some techniques to prevent this but it isn't
> definite.  Its actually this very topic that made me throw my new OO book
> across the room and subscribed to this newsgroup :)

Actually, no; with Python anything goes as well, it's just that we
know to restrain ourselves and generally we don't access attributes
directly. There's an idiomatic way to indicate 'this is private',
which has no practical effect whatsoever, which is to prepend an
underscore in front of the attribute or method you want to be
private (or protected, for that matter):

class Foo:
   def __init__(self):
        self._private = 1
  
   def _privateMethod(self):
        pass

There is also another way that *does* have an effect on the language,
though it doesn't go very deep (it does some name mangling), which is
to prepend two underscores in front of the thing you want to be private.
Note that this also disallows easy use from subclasses and such, so I
generally don't bother to use that and use the single underscore convention.
    
[snip]
> I've mentioned before that I'm real new to OO.  How should I approach it in
> Python?

Python is a nice language to do OO in, I think, because it doesn't
burden you with too much baggage; static type checking in particular
adds a lot of programmer overhead that Python luckily doesn't have. 
That said, it may be possible that static type checking makes OO more
clear for some people -- since Python is very liberal in what it allows
you to do, you do have to know how to restrain yourself.

>  Has anyone learned OO just from Python?  Or should I study OO
> theory else where and then apply it to Python?

I already knew OO before I came to Python, so I don't really know. However,
I'd consider Python a good language to learn OO in, even though it calls
for a little more programmer self-restraint, it isn't very difficult
to do this, and it's not as if C++ or Java don't call for plenty of
programmer discipline all over the place either -- more so than Python.

>  I know this is bordering on
> the question of how do I do OO but I really know very little about it...
> enough to know that I can benefit from it and basic ideas.  I understand the
> idea of a class and building objects from it but anything beyond that is
> still really new to me.  Any suggestions?

What's nice about OO is that it allows you to decouple the interface
from the implementation, and thereby it allows easy forms of polymorphism.
That sounds complicated perhaps, but imagine you have a game which
contains a bunch of objects; monsters of various kinds for instance.
Now imagine we have a list filled with a number of different monsters,
and each type of monster can be activated. When activated the monster
will do something, dependent on what type of monster it is, and perhaps
various other factors.

If you don't use OO in your Python program
(just using classes as a form of record), code to do that may look
somewhat like this:

# just an empty record we'll fill later; an empty dictionary is virtually
# the same in Python, in fact.
class MonsterRecord:
    pass

# create a record for a monster and fill it with data
green_monster = MonsterRecord() 
green_monster.type = "GREEN_MONSTER"
green_monster.strength = 15

# create purple monster
purple_monster = MonsterRecord()
purple_monster.type = "PURPLE_MONSTER"
purple_monster.strength = 10

# create orange monster
orange_monster = MonsterRecord()
orange_monster.type = "ORANGE_MONSTER"
orange_monster.strength = 20

# another one, but weaker
orange_monster2 = MonsterRecord()
orange_monster2.type = "ORANGE_MONSTER"
orange_monster2.strength = 10

# put them in a list
monsters = [green_monster, purple_monster, orange_monster, orange_monster2]

# a function that given a list of monster, performs action for each of them
def perform_actions(monsters):
    for monster in monsters:
        if monster.type == "GREEN_MONSTER":
            print "The monster says: Booh!"
        elif monster.type = "PURPLE_MONSTER":
            print "The monster sings: We are a happy family!"
        elif monster.type = "ORANGE_MONSTER":
            print "The monster says: monster wants orange!"
            if monster.strength > 15:
                print "The monster grabs your orange and eats it!"

# and call the function
perform_actions(monsters)

########################
Now we'll do the same, OO style:

class Monster:
    def __init__(self, strength):
        self.strength = strength

class GreenMonster(Monster):
    def action(self):
        print "The monster says: Booh!"

class PurpleMonster(Monster):
    def action(self):
        print "The monster sings: We are a happy family!"
 
class OrangeMonster(Monster):
    def action(self):
        print "The monster says: monster wants orange!"
        if self.strength > 15:
            print "The monster grabs your orange and eats it!"

# create some monsters and put them in a list
monsters = [GreenMonster(15), PurpleMonster(10), OrangeMonster(20),
            OrangeMonster(10)]

# and the function to perform all actions
def perform_actions(monsters):
    for monster in monsters:
        monster.action()

# let's call it
perform_actions(monsters)

In the OO example I've exploited a number of features generally associated
with OO programming (though good non-OO and OO programming styles aren't
far away):

  * interface/implementation separation leading to polymorphism

    The most important; it's easy to add new monsters with different
    behavior, without having to change anything in perform_actions().
    In the non-OO example, we'd have to extend perform_actions() each
    time we have a new monster. For a single type of action (method)
    this is okay, but in real programs this generally isn't the case;
    and then you'd need to go through your program and add 
    actions all over the place.

    You can do the same with a dictionary (hash table) indexed by
    monster type and returning some function to call, but why do it the
    hard way when there's an easy way (use classes and method).

  * inheritance

    Neat, but less essential to OO than is often thought. Since all
    monsters in my example have a 'strength' attribute, I've made
    all monsters inherit from the 'Monster' superclass, which has..
 
  * a constructor

    A constructor that sets the strength attribute. Constructor functions
    returning a record are of course not hard to do in a non OO way.

I've been talking about monsters in my example, but it could apply to
GUI widgets, or different type of objects that can all be treated as 
files (on disk file, in memory file, even network transparent file if
you wanted to), and so on.

A good book to learn more about common structures you can find in OO
programs is "Design Patterns".

>>The Python community's reputation is that it's friendlier than the Perl
>>community, the flame war about variable initialization in the do..until
>>thread notwithstanding. :)

> I heard something about curley braces as well.  No {} for blocks?  Thats
> going to take some getting used to :)

It's easier to get used to than most people think. I was used to it
within a few days at most; I was definitely used to { and } before that.
Using an editor that supports Python's indentation helps -- I myself
am happy with Python mode for emacs, which you can find on the Python
website.

>>I've seen people beinn pleasantly surprised by the quality of answers
>> they've received in this newsgroup, so you may like it.

> I know I have been.  Nothing like a friendly newsgroup to convince me to
> switch -- at least take a break from perl for awhile to see how the other
> side lives.

Great! I'm probably repeating answers others have already given --
I saw the thread has grown. I'll go read it now myself.

Regards,

Martijn
-- 
History of the 20th Century: WW1, WW2, WW3?
No, WWW -- Could we be going in the right direction?



More information about the Python-list mailing list