Raising objects

Steven Taschuk staschuk at telusplanet.net
Wed Apr 30 12:27:34 EDT 2003


Quoth Alex Martelli:
> Steven Taschuk wrote:
  [inability to raise new-style objects]
> > I don't have a real use case either, but it does seem rather
> > arbitrary.  Is there an implementation reason for this restriction?
> 
> In a sense, yes: there is no way to check if something "is a new-style
> class" as opposed to "any type whatsoever" -- so one could end up
> raising lists, tuples, strings (shades of the past...), whatever.

How about this?

    >>> def newstyle(obj):
    ...     """Whether obj is an instance of a new-style class."""
    ...     return hasattr(obj, '__class__') \
    ...            and issubclass(obj.__class__, object)
    ...
    >>> class OldStyle: pass
    ... 
    >>> class NewStyle(object): pass
    ... 
    >>> newstyle(OldStyle())
    0
    >>> newstyle(NewStyle())
    1
    >>> newstyle(Exception())
    0

This function can even be used directly on the classes:

    >>> newstyle(OldStyle)
    0
    >>> newstyle(NewStyle)
    1
    >>> newstyle(Exception)
    0

(Since the type 'type' is new-style but the type 'class' is not.)
It would produce counterintuitive results in such use if it were
possible for a new-style class object to be an instance of an
old-style class...  is that possible?

This function does report that strings and lists are new-style.
Aren't they?

> What I hope to see happen eventually is a spec that raise can use:
> 
>   -- any subclass of Exception (by that time a new-style class), OR
>   -- for backwards compatibility any old-style class, OR
>   -- for VERY backwards compatibility, any string
> 
> [and also INSTANCES as well as classes for the first two cases].

That seems reasonable.

But is there a problem with being able to raise anything?  Perhaps
some class of easy-to-produce bugs that I'm not seeing?

What I'm imagining at the moment is this: suppose you can raise
anything, and except clauses identify the exceptions to be caught
by their class.  The only problem I can see with this is that it
clashes with the present (backwards-compatible) treatment of
raised strings:
    try:
        raise 'foo'
    except 'foo':
        print 'wah'
wouldn't print 'wah', since 'foo' is not an instance of 'foo'.
You'd have to do something like
    try:
        raise 'foo'
    except str, e:
        if e == 'foo':
            print 'wah'
        else:
            raise
which is ugly.

So, suppose that strings were special-cased for backwards
compatibility:

    def exceptmatch(exception, classtomatch):
        """Whether an except clause specifying classtomatch should
        catch exception.
        """
        if isinstance(classtomatch, str):
            return exception == classtomatch
        else:
            return isinstance(exception, classtomatch)

(I ignore for simplicity except clauses which match more than one
class.)

Is there a problem with this scheme?

> Exactly: even in my hoped-for new spec, you'd have to wrap this
> in a subclass of Exception.  Facilitating the [ab]use of the
> exception mechanism for generalized control flow is, I suspect,
> NOT on the list of priorities in the BDFL's mind;-).  Feel free
> to open a PEP to settle that beyond any doubt, though...;-)

Heh.  I imagine you're right.  I'd argue in favour of a scheme
such as above chiefly on the basis of regularity (rather than for
making my silly example work).

I just don't see a good reason not to be able to raise new-style
objects, so to me it's an arbitrary restriction and as such makes
the language slightly uglier.  (It is, of course, a very minor
issue; I hadn't even noticed that Exception is old-style until
this thread.)

-- 
Steven Taschuk                               staschuk at telusplanet.net
"[T]rue greatness is when your name is like ampere, watt, and fourier
 -- when it's spelled with a lower case letter."      -- R.W. Hamming





More information about the Python-list mailing list