Class Variable Question

Alex Martelli aleaxit at yahoo.com
Tue Apr 10 07:58:35 EDT 2001


"Robert Johnson" <rjohnson at exotic-eo.com> wrote in message
news:3ad2a7dd$0$47987$e2e8da3 at nntp.cts.com...
> > The original poster was very explicitly talking about a *class* object,
> > not an *instance* object, which is why I didn't provide this pretty
> > standard part -- it doesn't work on class-objects (nor modules, &c).
> >
> Actually I was referring to the instance of the class (I use the term
> "Object" as meaning the instance of the class).  Most books I have read
use
> the term "Object" in this manner.  Sorry for the confusion.

Ooops.  Most languages don't give you classes AS objects, but
quite a few do -- not just Python, but, Smalltalk too, etc etc.

If you *DO* want to ward _instance_ objects specifically, then
you can in fact easily do so, since you can have a __setattr__
method which gets called anytime something is trying to bind
or rebind any of the instance's attributes.


> I think the feature I was looking for was something similar to the Options
> Explicit option of Visual Basic.  Sometimes I type fairly quickly and as
> such have been known to transpose letters.

I type very fast, make lots of typos, used to religiously force
Option Explicit in VB, come from a mostly compile-time-checked
languages background, and was perfectly convinced that lacking
compiler checks on my spelling meant doom in any large task.

I was wrong.


> I would have much preferred to
> catch a compile-time error rather than have to move line-by-line through
my
> code looking for the misspelled term.  This wouldn't be a big deal for a
> small program, but if I planned to develop anything of scale, this could
> really pose some serious problems.

It _could_, but it won't.  If your unit-tests are anywhere close to
1/10th as large as they should be, they'll catch all your typos 'hey
pronto'.  If your unit-tests are even skimpier than that, your software
is going to be so frail and weakly anyway that a few more uncaught
typos aren't going to matter one way or another.

Your C++ compiler doesn't catch all the typos you can make where you
type '+' while meaning to type '-', or '>' intending '<', etc, for
example.  *IS* that a major issue with software development?  You
know it isn't -- just a small recurring annoyance, as your early
tests catch THAT stuff pretty soon anyway; yeah, you WOULD get 1/2
of 1% better productivity if that could somehow be caught even
earlier, at compile-time, but, don't you WISH all problems in the
world were as tiny as this one?  The situation is essentially the
same for assigning to 'foo.plikko' while meaning 'foo.plokko' (it's
better for _reading_ non-existent attributes, as you instantly get
an exception for that) -- an occasional small annoyance which your
early unit-tests catch very effectively anyway.

In fact, in my experience it's not worth the 3-lines-of-code bother
to add a __setattr__ method (or get it from a mixin-inherited class)
to get marginally-earlier diagnostics...


> In fact, most authors of Visual Basic advise to turn Options Explicit on
> because it is a source of problems for the average Visual Basic
programmer.
> I can't imagine it not being a source of bugs, especially when code gets
> large.  I understand that some may see it as a feature, but for me it
would
> be something I would like to turn off.

You can (for *INSTANCE* objects, only, NOT in the general case: not
for module-objects, class-objects, etc, etc), with the __setattr__
trick.  It's probably not WORTH doing, but it's surely DOABLE.

(A more general solution would require the ability to 'lock' a
dictionary against certain modifications, but that's another issue).


> I am coming from the C++ world where if one wanted to extend a class, one
> would override the base class (or insert into the original class if you
had
> the source) and add any additional variables to the new class.  It just

You can extend by inheritance in Python, too, of course.  You just
get more options regarding what you can do.

> seemed odd to me that one could just add things on the fly, but that is
just
> my bias.

Consider an *instance* of a std::map< std::string, std::string >, for
example.  You CAN "just add things on the fly" to it, can't you?  Isn't
it handy, indeed sometimes crucial, to be able to add any foo->bar
mapping entry to the class on the fly, as and if and when the need
arises, at runtime, rather than having to pre-declare all the set
of 'keys' that are going to be allowed and/or mandatory for all
instances of such a type...?

A Python dictionary is based on the same idea -- except it's somewhat
more general and flexible (and faster, as it uses hashing rather than
red-black trees, but that's another issue).  OK so far?  So, the
concept of "just add things on the fly" _isn't_ so alien after all!-)

The "Python difference" is that you can choose to use attribute
syntax (foo.bar = 'baz') as a handy, elegant shortcut for mapping
syntax (foo.__dict__['bar'] = 'baz').  Just as you can 'add on
the fly' with the mapping syntax, so, of course, you can with
the attribute syntax -- why not, indeed?  If it's useful to lack
constraints on the mapping-syntax use, why should it be so heavily
detrimental to similarly lack constraints when the syntax sugar is
of the attribute-syntax ilk instead?  [The semantics of the
attribute syntax, and the equivalent setattr(foo, 'bar', 'baz')
are NOT identical to dictionary-assignments, because, if foo is
an instance-object, *and* has a __setattr__ method, that will
also come into play... an extra "hook" you, as class-author, get
to do funky and brilliant things upon attribute-assigment!-)].


I do believe it would be occasionally (and marginally) useful to
be able to "lock" a dictionary object against further changes
(have it generate a suitable exception if a forbidden change
is attempted -- _whatever_ syntax-sugar it's attempted with!-).

Specifically, have settable "option-bits" that may [a] disallow
addition of not-already-present keys, or [b] disallow changes
to the values of already-present keys, or [c] both of the above
(and maybe also a bit that, when set, disallows changes to the
option-bits themselves forevermore, 'freezing' modificability
of the dictionary object in the current state).

A completely-forever-unmodifiable dictionary object could then
become hashable (usable as a key in another dictionary) --
today, you have to use tuple(thedict.items()) for that rather
than thedict itself; accidental, unintended modification or
overwriting of attributes of many kinds of objects (all that
rely on dictionary to hold their attributes -- including
module-objects, so [global] variables could become 'readonly'
this way, too); small advantages, but pretty cheap ones.

And maybe we could cut short such thread as this one by
pointing out how easy it is to freeze an object's dictionary
against further modifications -- the time thus saved on
comp.lang.python would probably exceed that actually saved
by USING this new tweak on dictionaries...!-)


Alex






More information about the Python-list mailing list