Re: Thoughts and proposals about types and classes

Tim Peters (tim@ksr.com)
Fri, 10 Sep 93 00:22:01 -0400

There's a footnote in the reference manual, to the effect that Python
"should" distinguish among classes implementing sequences, mappings, and
numerics. There it's in the context of explaining the strange coercion
behavior for __add__ and __mul__ methods, but you're surely right that it
could have broader use. The presence or absence of an __isnumeric__/
__issequence__/__ismapping__ attribute seems a decent way to make this
distinction.

I'm not sure what _meaning_ to ascribe to these predicates, though!
E.g., you've found it convenient to define a sequence type (the buffered
input class) that doesn't want to implement __getslice__ (for efficiency
reasons), and I've found it convenient to define a numeric type (the Date
class) that doesn't want to implement _most_ of the "numeric" operations.

Similarly, I suspect we both implement one-shot (throwaway, whatever)
sequence/mapping/numeric classes, purely for short-term syntactic
convenience, that don't implement most of the sequence/mapping/numeric
special methods. And, e.g., I suspect that nobody yet has implemented a
new numeric type that supports the __lshift__ method -- not that it can't
be useful to do so, but that it's bound to be useful only rarely for a
new numeric type (what could it mean to shift a complex number? etc).

So I worry that if isnumeric(thing), issequence(thing) (etc) are added to
the language, we'll still be left wondering "OK, isequence(thing)/
isnumeric(thing)/whatever was true, but what _operations_ does this thing
support?".

If the answer is "it's up to the user to define-- and stick to --their
own conventions on this", there's little reason to build it into the
language, since the same effect can be easily-enough achieved "by hand",
by building the knowledge into a common module. But if Python defines--
and enforces --some convention, we'll find it overly restrictive unless
it's too weak to solve the problem.

About using try/except to catch the kinds of errors in question, fully
agreed it's a bad approach. When implementing new types that are
misused, the "in the bowels" exceptions are as often attribute errors as
type errors. Sticking both kinds of exceptions on an enclosing "try" is
just begging for trouble.

> But if python actively discourages error checking by making it awkward
> or difficult or time consuming, then its use for more ambitious "end
> user" programs may be limited.

Well, even now it's less awkward in Python than in, e.g., COBOL, BASIC, C
or Fortran, but the latter get used anyway for far too many end user
programs that are far too ambitious <grin>.

I'm not convinced Python _can_ supply a solution to this, but it would
help if building one's own solution were a little cleaner. E.g., a short
way to spell "type(THING) is type(a_class_instance) and THING.__class__
is CLASS" (or "... and (THING.__class__ is CLASS or CLASS in
THING.__class__.__bases__") would save a fair amount of discouraging
tedium.

> ...
> 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".

Your objection made good sense to me!

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

But I do <grin>. Note that, unlike __getslice__, __getitem__ can get
passed absolutely anything (ints, regexps, modules, lists, functions,
files, ...). I have code that depends on that <wink>.

and-my-own-code-is-the-measure-of-all-things-ly y'rs - tim

Tim Peters tim@ksr.com
not speaking for Kendall Square Research Corp