Re: Thoughts and proposals about types and classes

Steven D. Majewski (sdm7g@elvis.med.virginia.edu)
Thu, 9 Sep 1993 12:25:06 -0400

On Sep 9, 3:21, Tim Peters wrote:
>
> I've since taken the "the only requirement is that an object supports the
> operations that are actually applied to it" as a useful design principle,
> and found that most of my uses of "type" vanished as a result, and that
> the code became more general even while becoming simpler.
>
> A neat example of the latter phenomenon is a rework of the Complex
> module: by pruning out overly-protective uses of "type", I got a Complex
> module that works fine for Complex numbers whose real & imaginary parts
> are arbitrary-precision rationals (or integers, or-- indeed --are Complex
> themselves: any objects that "support the operations applied to them").
> This is slick! "type" is really needed in only a few places, and half of
> those just to worm around the non-coercion of + and * arguments.
>
> So I pretty much stopped worrying about the type system. However, since
> I'm the primary consumer of the classes I write, I'm happy with obscure
> error msgs from deep in the bowels of the class implementation; another
> user would doubtless much rather be told up front "you can't divide a
> complex by a dictionary" at the top level, and supplying that
> friendliness would put me right back in the "type" business. Messy
> issues!
>

You're probably right! Doing some upfront error checking on the args
to give a coherent error message was actually the primary use I had
in mind for a better type/class/subclass test. And even there, I can
always wrap the whole thing with a "try: ... ; except TypeError: "
to give *MY* error message, rather than the one from "deep in the
bowels". But, as in Guido's previous remarks contra-non-qualified-excepts
( Try: ; Except: #(everything) ), in those few cases when I actually
KNOW exactly what I want, I would like to be exactly specific, and not
worry that I might catch an exception that is not from the expected
cause. Also, the info from an exception might not be specific enough
( like WHICH arg was bad? ) unless you first test some guarded
commands:
for ARG in ARGLIST:
try: tmp = ARG + 0 # or perhaps tmp = ARG[0] for sequences
except: raise some_more_specific_error

I've got code where I DO check for type(()) or type([]).
And I would prefer, for just the reasons you state, to not be
*overly* restrictive: I probably really mean to test for is_a_mutable_
sequence? , not <type 'list'>. So I'm looking for an easy way to
do this.

def issequence( s ):
if type(s) in ( type(()), type([]) ): return 1
if type(s) <> TypeInstance : return 1
for X in ( '__len__', '__getitem__', '__getslice__' ):
if not hasattr( s, X ) : return 0
return 1

is not too bad, but the list gets longer for mutable sequences and
numerics. I don't think the convention of having to implement
__isnumeric__ or __issequence__ would be too much to ask to
make the implementation of issequence() of isnumeric() easier
and more effecient. And it would also be a promise of some
"reasonable" semantics. ( and like all promises, you should consider
the promiser! )

[ That was my minimal & initial proposal - the other ramblings were
an effort to see if there was something more general that could
be done with the type/class system. ]

Your comments about _you_ being the primary consumer of your classes
is on the mark. Most of my use of python is when I want a quick
( and possibly dirty ) solution, and I don't really want to bother
coding argument checks and error messages. In those cases, python's
default behaviour is quite sufficient. But if python actively
discourages error checking by making it awkward or difficult or
time consuming, then it's use for more ambitious "end user" programs
may be limited.

[ This brings us back to the "What are YOU using python for" thread.
More entries are hereby solicited! ]

> > [steve]
> > Which leads me to comment on the 2nd half ... One result of the
> > experiment was discovering that my attempt at a "string index" for a
> > sequence didn't work : the index can only be an int!
>
[ ... ]
>
> tickled-by-what-you-_wanted_-to-do-with-__getslice__-all-the-same-ly
> y'rs - tim
>

I can see reasons why it *SHOULDN'T* work - both technical/implementation
reasons AND semantic/reasonable-expectation reasons. I was just playing
around and was trying to see what I could and couldn't do. I don't want
it to be interpreted as a request or complaint that it didn't work.
Especially in the light of my pedantic (actual) complaint that
array.read( file, count ) OUGHT to be array.readfrom( file, count )
since there should be a reasonable expectation that obj.read() is a
method of something that can be "read" and takes an argument of "how
much" . ( Or, at least, there *WAS* a reasonable expectation until array
objects were added to the language. The counter point-of-view is than no
methods except those starting with "__" should be considered "sacred".)

I don't think 'seq[int]' is an unreasonable restriction.

-Steve Majewski (804-982-0831) <sdm7g@Virginia.EDU>
-Univ. of Virginia Department of Molecular Physiology and Biological Physics