Raising objects
Steven Taschuk
staschuk at telusplanet.net
Thu May 1 14:58:58 EDT 2003
Quoth Alex Martelli:
> Steven Taschuk wrote:
[...]
> > So what then is the distinction between new-style classes and
> > types? (Other than that types are not quite reliably subclassable
> > yet, or so I hear.)
>
> There is no way to reliably draw that distinction -- we're in
> transition and in a mess:-).
Oh, good. (I thought I might be missing something simple.)
[...]
> > But usually in Python we do not care whether an object inherits
> > from a specific subclass; we only care whether it has the
> > attributes we need it to have. Why should the error-reporting
> > facilities of Exception be any different?
>
> Exception handling is one of the very few places in Python that
> DO care who inherits from what! A few others are marginal and
> explicit -- issubclass, isinstance, calling unbound methods --
> but only in exception handling does inheritance play such a
> major role. So, I think the "usually" doesn't extent to this case.
Another good point!
On reflection, I notice the (fairly obvious) point that a
programmer who wanted to *replace* the error reporting facilities
could quite easily do
class MyErrorReporting(Exception):
... override relevant methods ...
class HullBreachError(MyErrorReporting):
pass
Between this and the fact that we can raise anything by wrapping
it in an Exception, I think I've run out of pragmatic reasons for
being able to raise anything. :(
[...]
> I would explain my desiderata differently: raising any instance
> of NewException raises it; raising any subclass of NewException
> instantiates it (optionally with the provided argument[s]) and
> raises the resulting instance.
>
> So, the exception that is propagating is ALWAYS an instance of
> NewException. An except clause catches an exception E, if and
> only if it names a type of which E is an instance.
Ah. I'd be content with that. (I still feel the appeal of "raise
anything", but am slowly, reluctantly, being made to see that it
creates more -- and more serious -- problems than it solves.)
What really bothers me about the
raise ValueError, 'n < 0'
syntax is that the relationship between the two parts is precisely
that between the class of an object and that object's individual
state -- ValueError is the type of error, and 'n < 0' is state
which specifies what *this* error is. The normal way to express
that relationship in Python (the one obvious way to do it?) is
with classes and instances of them, such as with
raise ValueError('n < 0')
which makes much more sense to me. I think you and I are in
concord here; in your desiderata above you'd have the comma syntax
be equivalent to the instantiating syntax. (As far as I can know,
it already is, actually.)
I don't see any benefit to the comma syntax these days, other than
backwards compatibility. Indeed, it seems to me slightly harmful,
not so much because it looks like raising a tuple (though it
does), but because it creates a false analogy between the raise
syntax and the except syntax:
>>> foo = 'bar'
>>> try:
... raise ValueError, foo
... except ValueError, e:
... pass
The syntactic parallel suggests that e is foo; but in fact e is an
instance of ValueError which contains foo.
> The backwards-compatibility hacks aren't in my "desiderata" --
> and it MIGHT conceivably be possible to remove string exceptions
> one day and just make Exception newstyle (well, one can dream,
> but I DO dream of a day where classic classes have gone!).
So do I, brother, so do I.
[...]
> > Hm... maybe I should write a PEP.
>
> Yes, I agree you should -- nothing as major as this is gonna happen
> without a lot of PEPping.
I might yet do so. (For now I'm still changing my views too
rapidly; I'll look at it again when I've settled down.)
--
Steven Taschuk staschuk at telusplanet.net
Receive them ignorant; dispatch them confused. (Weschler's Teaching Motto)
More information about the Python-list
mailing list