読者です 読者をやめる 読者になる 読者になる

CUBE SUGAR CONTAINER

技術系のこと書きます。

Python: EAFP スタイルと LBYL スタイル

Python

プログラミングの方針に EAFP スタイルと LBYL スタイルという分類の仕方があることを知った。 これはそれぞれ「Easier to Ask for Forgiveness than Permission」と「Look Before You Leap」の頭文字から取られているらしい。 ざっくり言えば EAFP スタイルは問題が起こってから対処する方針で、反対に LBYL はあらかじめ問題が起こる要因を取り除いておく方針を表しているようだ。

これは別に Python に限った話ではないんだけど、僕は Python の用語集を読んで知った。 そして Python では EAFP スタイルが用いられることが多いらしい。

用語集 — Python 3.5.2 ドキュメント

ちょっとしたサンプルでそれぞれのスタイルの考え方について知ってみよう。 まず、題目には割り算を選んだ。 サンプルコードでは、どちらも mydiv() 関数というふたつの値を取って割り算をする関数を定義している。 ただし、割り算は 0 で割ることができない。 それに対して、それぞれのスタイルではどのように対処するかを考えてみる。

EAFP スタイル

EAFP スタイルでは問題が起こったときにそれを対処する。 すなわち 0 で割り算したときの ZeroDivisionError 例外を拾って、何らかの処理をするということだ。 ここでは 0 で割ったときは結果として None を返すことにしてみよう。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import division


def mydiv(a, b):
    """割り算をする関数 (EAFP スタイル)"""
    try:
        return a / b
    except ZeroDivisionError:
        # 問題が起こったときに例外などを補足して対処する
        return None


def main():
    print(mydiv(1, 0))


if __name__ == '__main__':
    main()

実行結果は次の通り。

$ python eafp.py 
None

期待通り返り値に None が得られている。

LBYL スタイル

LBYL スタイルでは、あらかじめ問題が起こる要因を取り除いておく。 今回の場合、問題が起きるのは引数 b に 0 が入ったときだ。 なので引数 b に 0 が入ったときを想定して、あらかじめそれに対処するコードを入れておく。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import division


def mydiv(a, b):
    """割り算をする関数 (LBYL スタイル)"""

    # あらかじめ問題が起こる要因を排除する
    if b == 0:
        return None

    return a / b


def main():
    print(mydiv(1, 0))


if __name__ == '__main__':
    main()

実行結果は次の通り。

$ python lbyl.py 
None

まとめ

今回はプログラミングの方針として EAFP スタイルと LBYL スタイルというふたつのアプローチについて学んだ。 Python では EAFP スタイルが用いられることが多いらしい。 とはいえ、これはどちらのスタイルが優れているとかそういう話ではないだろう。 このプログラミング言語だからどちらかで書かなければいけない、という話でもなくバランスの問題のように感じた。