Python evangelists unite!

Gareth McCaughan Gareth.McCaughan at pobox.com
Thu Nov 29 19:51:14 EST 2001


brucehapman at hotmail.com wrote:

> Okay, I was extolling the benefits of Python to a friend of mine. He
> took strong exception to Python's OO model. <here we go again...>
> 
>      ME: Python's great--you can add members to instances OR classes
> on-the-fly!
>  FRIEND: Why would you want to do that? 
>      ME: Uh...
>  FRIEND: Besides, that's awful Object Orientation. If I start adding
> attributes to an instance of a class, it ceases to be an instance of
> that class. If I create a bunch of instances of the same class, they
> should be the same; they should have the same members.

Twaddle. They should provide the same interface. What members
they have is completely irrelevant to that, unless those
members are part of the interface you specify. (It so happens
that in Python there isn't really an in-language mechanism for
saying what's part of the interface and what isn't, but that
doesn't mean your objects don't have interfaces.)

And, of course, there's no law that says Python's objects
are only to be used for "proper" elegant OO programming.
They have other uses. :-)

>      ME: Yeah, but with dynamicism, I can add a new pane to a GUI
> while it's running. I just change an instance to include a new pane,
> and...
>  FRIEND: That's pretty cool, but it's not a reason, in and of itself,
> to make a language so dynamic. There must be some advantage to being
> able to add attributes during runtime. What are they?
>      ME: Uh...
>  FRIEND: And another thing! What's with encapsulation? There's no
> private!?!?!?

Here's an entry from my personal quotes file. It's about
CLOS (the Common Lisp Object System), which in most respects
is a very different beast from Python's object system; but
they have a similar attitude to encapsulation.

    ... it's just that in C++ and the like, you don't trust _anybody_,
    and in CLOS you basically trust everybody.  the practical result is
    that thieves and bums use C++ and nice people use CLOS.

            -- Erik Naggum

Someone who can't write well-formed OO programs without a
mechanism like "private" has serious problems with their
ability to write comments, or their ability to write other
documentation, or their discipline, or something.

Besides, in C++ at least, you can say

    #define private public
    #include "my-class.h"
    #undef private

Yow!

>      ME: <Screaming and running for cover>
> 
> So, I need some help. I've checked out c.l.p and some on-line
> articles, and I just can't find good practicle examples of a program
> that adds members to instances (or classes) at runtime. Anybody got
> any? I don't want to have to start avoiding my friend....

The main advantage isn't the ability to add members at runtime
as such. That's just a side-effect of the fact that you don't
need explicit declarations of what can go in a class. And
*that*'s good for three reasons.

  - Less repetitetition. Don't you just hate having to write
    the same thing twice in C and C++? Programming's bad enough
    for the wrists without having to write a pile of redundant
    code.

  - Handy for exploratory programming, where you sit at an
    interactive prompt and play with things. If you suddenly
    realise that you can make something go 10 times faster
    by cacheing a crucial piece of information inside your
    objects, it's nice that you can just add it and have it
    work. I suppose that *is* adding members at runtime,
    actually, but I suspect it's not the sort you had in
    mind.

  - One handy Python idiom is using an empty class definition
    to provide things like "structs" in C.

        class Empty: pass
        stuff = Empty()
        stuff.largest_prime = 44
        stuff.modulus = -1
        # etc

Having said that being able to add members at runtime isn't quite
the point, let me sort-of-contradict that by describing something
slightly icky I do in a program I use at work.

I'm collecting data from a sensor, and I want to be able to do
various bits of processing on the data. But not every packet of
data needs all the processing done on it. And, once all the
processing is done, I then want to stash a large number of
data-packets into a pickle for later use by another program.
I don't want my pickles to be hundreds of megabytes long.

So, my class looks a little like this:

    class Packet:
      def __init__(self, data):
        self._data = data
        self._processed = 0
      def ensure_processed(self):
        self._squares = map(operator.mul, self._data, self._data)
        self._average = reduce(operator.add, self._data) / len(self._data)
        self._sumsofquares = reduce(operator.add, self._Squares)
        # blah blah blah
        self._processed = 1
      def minimize(self):
        try:
          del self._squares
          del self._sumofsquares
          # blah blah
        except:
          pass

    my_packets = build_many_packets(100000)
    do_hairy_stuff_with_packets(my_packets)
    map(Packet.minimize, my_packets)
    cPickle.dump(open("data.pickled", "w"))

(Only a little like that; what it actually does is a lot more
complicated.)

-- 
Gareth McCaughan  Gareth.McCaughan at pobox.com
.sig under construc



More information about the Python-list mailing list