Address
304 North Cardinal St.
Dorchester Center, MA 02124

Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM

Pythonでユーザー独自の例外を定義し使う方法の解説

Pythonでユーザー独自の例外を定義し使う方法を、公式ドキュメントのコード例を使って解説。Exceptionクラスの継承とraise文の使い方とは?

Pythonでユーザー独自例外定義の作り方と使い方を初心者向けにわかりやすく解説

この記事の1つ前の記事で、Pythonにおけるtry文(try節+except節)について初心者向けの解説をしました。下の記事がそれです。

その記事では主に、try~exceptの基本的な使い方を中心に説明しましたが、今回の記事はその応用編のようなものです。

具体的には、独自に例外を定義(作成)して、それをtry文と組合わわせて使う方法の解説となります。

今回は公式ドキュメントのコードをそのまま使って解説します。

公式ドキュメントにあるコード例

Python公式ドキュメント「エラーと例外」のページには、下のコード例が記載されています。(一部、私がコメントを入れたりして、改変していますが大枠はそのままです)

class B(Exception):
    """#新しい例外をExceptionクラスから継承(継承はBaseExceptonではなくExceptionを使う。クラスBそのものが例外になる.
    """
    pass
class C(B):#例外クラスBを継承するのでCも例外クラス
    pass
class D(C):#クラスCと同様に例外
    pass
for cls in [B, C, D]:
    try:
        """例外としてBが発生するので、
          try節からexcept節へ移動する
        """
        raise cls()
    except D:
        print("D")
    except C:
        print("C")
    except B:
        """例外はBであるので
            この節が最初に実行される.
        """
        print("B")

これを実行すると、次のような結果になります。

B
C
D

B→C→Dという順番になっていることに注意してください。この順番が今回のポイントです。

それでは次にこのコード例を解説していきます。

解説

Exceptionクラスを使った継承(派生クラス)で、ユーザー独自の例外を定義する

まずPythonにおける用語「エラー」そして「例外」については、この1つ前の記事「Pythonにおけるtryとexceptによるエラーと例外処理についてわかりやすく解説」で説明しましたので、そちらをご覧ください。

class B(Exception):
    """#新しい例外をExceptionクラスから継承(継承はBaseExceptonではなくExceptionを使う。クラスBそのものが例外になる.
    """
    pass

まず最初のこの部分ですが、「class B(Exception)」というのは、Pythonがそもそも標準で用意しているExceptionというクラスを継承しているという宣言です。このExceptionクラスは、システム終了以外の「例外」を生み出すクラスです。

そして、クラスの継承というのは、今回は詳しく解説しませんが、簡単にいえば継承させることで「親クラス」の機能を使えるようにするというイメージです。

そもそも、公式ドキュメントでは、

全てのユーザ定義例外もこのクラスから派生させるべきです。

か指示されています。派生させるとは、クラスの場合は継承を使うと同じ意味です。

この継承により、class Bは親クラスExceptionの「例外」を生み出す機能を使えるようになり、言い換えるとユーザーが新しく「例外」を定義していることになります。class Bは例外となるわけです。

なお、上述のようにExceptionクラスは「システム終了以外」の例外を生み出すクラスですが、システム終了も含めて全ての例外を派生させるBaseExceptionというクラスもPythonには存在します。

class Cとclass Dについても考え方は同じです。

class Cはclass Bを継承します。class Bがそもそも例外でしたので、class Cも例外となります。

次にclass Dはclass Cを継承しています。class Cは例外でしたので、class Dも例外となります。例外ファミリー(一家)が増えていくという感じですね。

では次にfor以下の部分を見ていきましょう。

try~except

try~exceptの使い方・考え方についても「Pythonにおけるtryとexceptによるエラーと例外処理についてわかりやすく解説」をまた読んでみてください。

for cls in [B, C, D]:
    try:
        """例外としてBが発生するので、
          try節からexcept節へ移動する
        """
        raise cls()
    except D:
        print("D")
    except C:
        print("C")
    except B:
        """例外はBであるので
            この節が最初に実行される.
        """
        print("B")

この部分の処理の流れを書くと次のようになります。

・まず変数clsにリスト[B, C, D]から最初の要素B(class B、すなわちBという例外)が代入される

・try文中のtry節へ移動

・raiseは与えられた式を内容とする例外を発生させる文。cls()(つまり=B())という例外が指定されているため、Bという例外を発生させる


・try節中で例外発生

・except節へ移動。最初にexcept Dに設定された例外情報(ここではDという例外)に一致するかチェック。今はBという例外なので一致しない

・except Cへ移動。上と同じように例外がチェックされる。一致しない。

・except Bへ移動。一致する。よってprint(“B”)が実行される。

・for文のループ2回目がスタート。clsに今度はCという例外が代入される。

以下同じことが繰り返される

このような処理の流れの結果、

B
C
D

という文字の順番で結果が出力されるわけです。

いかがでしたでしょうか、少しわかりにくいコードだったかもしれませんが、ユーザー独自の例外を定義する方法とともに、クラスの継承、for文、try文などの使い方など初心者や入門者にはとても示唆に富むというか、勉強になるコードだったと思います。それゆえ今回は公式ドキュメントのコードをそのまま使わせてもらいました。

愛を分かち合いましょう