初心者プログラマのひとり勉強部屋

若葉マークのプログラマー☺️

【python入門】pythonチュートリアルで詰まった点(エラーと例外・継承の実行順序)

今回は、pythonチュートリアルで試験でも出題数の多い「エラーと例外」で詰まった点です。

docs.python.org

チュートリアルで以下の例文があります。

class B(Exception):
    pass

class C(B):
    pass

class D(C):
    pass

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


結果

B
C
D



流れはこのようになります。

f:id:mocomo012:20210122162351p:plain
例外の順番

B①→B②→B③
C①→C②→C③
D①→D②→D③

こちらのExceptionの順番を逆にすると結果が「BBB」になります。

class B(Exception):
    pass

class C(B):
    pass

class D(C):
    pass

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


結果

B
B
B

疑問
なぜ「BCD」にならないのか

答えは、継承にあります。

◾️継承
親クラスのメソッドや属性を派生クラスで使用できるようにすることです。 下記サイト様が大変参考になります。

Pythonのクラス(class)の継承に関する知識と方法のまとめ | HEADBOOST

上のチュートリアルの例文ではclassCはclassBを継承していて、classDはclassBを継承しているclassCを継承しています。
この場合のコードの派生クラスDの実行順序をmro()関数で見てみます

class B(Exception):
    pass

class C(B):
    pass

class D(C):
    pass

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

結果

B
B
B
[<class '__main__.D'>, <class '__main__.C'>, <class '__main__.B'>, <class 'Exception'>, <class 'BaseException'>, <class 'object'>]

派生クラスD→派生クラスC→親クラスB→基底クラス
の順で実行されていることが分かります。
チュートリアルで記載されているように、「最初に一致した except 節が駆動されるのです。」ので、D・C・Bのなかで最初のexceptであるBになるのでした。

継承の順番はこちらの記事を参考にさせていただきました。

www.sejuku.net