Classes in Python

Alex Martelli aleax at aleax.it
Fri Apr 18 21:21:52 CEST 2003


<posted & mailed>

Bill Martin wrote:

> I'm wondering about the value of allowing a class definition like this:
> 
>              class C:
>                pass

Each instance x of such a class C is a separate, initially empty 
namespace.  You can manage the namespace by adding and removing
names, querying if a name is present and what value it has if so,
and the like -- there are various tools you can use for that, such
as direct assignments and deletions:
    x.aname = 23
    del x.aname
and builtins such as setattr, getattr, delattr, hasattr.

Further, all the namespaces you thus generate have a common root,
class C itself -- at any time you can (using exactly the same
tools) manage that common root namespace.

Pretty useful indeed, if you need namespaces.  There are quite a
few common additions to the idiom, such an initializer to allow
handy initialization of a set of names in a namespace (instance)
while you're generating it:

class Bunch:
    def __init__(self, **kwds): self.__dict__.update(kwds)

Here I've used the canonical name for this Python idiom, as found
in the Cookbook.  Now, you can initialize a namespace at the
same time you're instantiating it, e.g:

apoint = Bunch(x=23, y=45)

and the usefulness keeps growing.  Use Advanced Google Groups Search
on this newsgroup for word 'metabunch' and you'll find even niftier
versions of this idiom based on custom metaclasses -- etc, etc.


> Now I can define a = c() and b = c(), then say a.x1 = 1.2, b.x2 = 3.5 or

Sure, that's using a and b as two separate namespaces, the most
fundamental and elementary use of the idiom.

> some such. If I try to print a.x2 or b.x1, I get an exception message
> basically saying those member variables don't exist. It seems to me this

Well, of course -- they're SEPARATE namespaces, by design!

> defeats one of the basic ideas behind OOP, that is to assign members to
> the class definition, thus ensuring that all instantiations of a class
> have the same member variables and methods. 

I'm not sure where you've read that this is "one of the basic ideas
behind OOP", but, wherever that may be, it's simply bunk -- it must
be an author having some hidden agenda and trying to pass off "static
typing" as somehow part of "OOP", presumably trying to convince you
that static typing must be good by association.  Fortunately, this
particular disinformation is easy to debunk, thanks to the fact that
Smalltalk, basically THE oldest OO language still in widespread use
(Simula67 was older, but it's not widespread these days), doesn't use
static typing -- when you send a message to an object, you can learn
at runtime that the object "doesn't understand" that message (i.e.,
doesn't have that method).  Why, some excellent OO languages don't
even HAVE classes -- just objects... if ANYTHING connected to classes
HAD to be part of OO, those language couldn't exist.  Bunk, as I say.

Don't believe everything you read...

> I know there must be a
> reason that python allows this kind of thing that I described, but I
> can't figure out what that reason could be. 

Practicality.

> To me, it looks like a very
> dangerous thing to do. 

Why so?  Please explain.  Python has dictionaries.  You can do:

    aa = {}
    bb = {}

and later

    aa['x1'] = 1.2
    ab['x2'] = 3.5

but now of course if you try to print aa['x2'] or bb['x1'], you 
get an exception message basically saying those items don't exist.

So: do you consider this "a very dangerous thing"?  How so?

And if that's not all that dangerous, then why should the syntax 
to do basically *exactly the same things* on top of a class (and
with even less redundant punctuation) suddenly become "very
dangerous"?!

If you don't see how these are exactly the same things, consider
that if you use your initial example and then do
    aa = a.__dict__
    bb = b.__dict__
you get exactly to this latter point, and viceversa.  If you do
not have any "behavior" (methods, i.e. executable attributes), a
class instance is basically a thin syntax wrapper around a dict,
with a few useful extra features that add absolutely no danger
whatsoever (and that you haven't even mentioned anyway).

> Can someone help me understand why we'd like to
> do it? Thanks,

Why we'd like to refer to a.x1 rather than aa['x1']?  Nicer and
smoother syntax.  Moreover, classes CAN have behavior, and thus
supply nicely polymorphic access to their functionality -- PLUS
they offer inheritance, so several instances can automatically
share some of their state (and behavior), etc, etc.  So, in fact,
there's a lot of practical, useful potential connected to that
"thin syntax wrapper".

You appear to think there are downsides and indeed "danger".
Can you help me understand what you think those downside are
and where the danger lies?  Thanks.


Alex





More information about the Python-list mailing list