Question

I was going through the Documentation of exceptions in python :-(https://docs.python.org/2/tutorial/classes.html#exceptions-are-classes-too)

I can't seem to find how this code works

class B:
     pass
class C(B):
     pass
class D(C):
     pass  

for c in [B, C, D]:
    try:
        raise c()
    except D:
        print "D"
    except C:
        print "C"
    except B:
        print "B"

Output:-

B
C
D

What's "pass" doing in the classes? Just by going over the documentation all i can get is objects of all the classes are made( Object creation order :- B,C and D) and exceptions are raised in their names, if that's the order then it explains the output B,C,D.

But if we replace excpet B with except D the whole output is changed.

class B:
     pass
class C(B):
     pass
class D(C):
     pass  

for c in [B, C, D]:
    try:
        raise c()
    except B:
        print "B"
    except C:
        print "C"
    except D:
        print "D"

Output:-

B
B
B

Now this makes my head spinning:/

How's the order of "except" changing the output?

I know i am missing something from the documentation, maybe because it's not very clear :(

Was it helpful?

Solution

Since C and D are subclasses of B, they are all caught by the except B clause. When catching exceptions, you need to always list the except clauses from most to least specific, because your exception is caught by the first one that applies.

From the documentation (emphasis mine):

The except clause(s) specify one or more exception handlers. When no exception occurs in the try clause, no exception handler is executed. When an exception occurs in the try suite, a search for an exception handler is started. This search inspects the except clauses in turn until one is found that matches the exception. An expression-less except clause, if present, must be last; it matches any exception. For an except clause with an expression, that expression is evaluated, and the clause matches the exception if the resulting object is “compatible” with the exception. An object is compatible with an exception if it is the class or a base class of the exception object, or a tuple containing an item compatible with the exception.

The pass statement is used where a statement is expected, but nothing else is needed. The class statement cannot have an empty body, but it is often better to use a docstring instead.

class B:
    """An exception that signals an error occurred"""

Syntactically, the docstring fills the need for a statement in the body of the class statement, but provides additional information as well.

OTHER TIPS

First except that matches is the one executed. So if all objects are instances of B and you have except B: at first place then the other excepts are not even considered.

The keyword pass is just a no-operation command - it does nothing. It is there just because there has to be something as Python source code is indentation based. In Java or C++ you would write empty function/class bodies as {}, in Python it's pass.

It seems to me like the order of your except statements is important because Python will follow the exception logic of the first true except statement it sees.

In the first example, the first line of output will be B because the class B is not a subclass of C or D. In the second example, all output will be B, because each class is a subclass of B.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top