Python Tips: Python で main 関数を定義することのメリット

今回は Python のスクリプトでエントリーポイントとなる main 関数を定義することのメリットについて説明します。

# わざわざ main 関数を定義してその中に処理を書く
def main():
    ...


if __name__ == "__main__":
    main()

Python では本来 main 関数を定義する必要はありませんが、経験者が書いたスクリプトではよく main 関数が定義されています。 筆者は Python を学び始めた頃にそういうコードを見て「必要ないものをなぜわざわざ書くのだろう?」とよく疑問に思いました。 今回は筆者自身がかつて抱いたこの疑問に答えてみます。

尚、 main という名前には特に制約はありません。 main という名前を使うのは慣習です。

main 関数を定義する」というのは、正確には上のコードのように、 main 関数を定義した上で、ファイル末尾に if __name__ == "__main__": という if 節を書いてその下で main 関数を呼び出すことを意味しますが、ここではかんたんに「 main 関数を定義する」という表現を使います。

Python で main 関数を定義することのメリット

Python スクリプトで main 関数を定義することにはさまざまなメリットがあります。

  1. 関数の定義を後ろに書ける
  2. 抽象度の高いコードを main 関数で示せる
  3. 処理の変更や差し替えがやりやすい
  4. テストが書きやすい
  5. 変数名の意図しない衝突を防げる

1. 関数の定義を後ろに書ける

Python では JavaScript あるようなスコープ内の変数の巻き上げが起こらないため、関数は定義後にしか使うことができません。

# 関数は定義よりも前で使うことができないので、このコードを実行するとエラーになる
func_a()
# => NameError: name 'func_a' is not defined


def func_a():
    ...

main 関数を使うことで、 main 以外の関数の定義を利用場所よりも後ろに書くことができます。

# エラーなく `func_a()` が実行できる
def main():
    func_a()


def func_a():
    ...


if __name__ == "__main__":
    main()

2. 抽象度の高いコードを main 関数で示せる

1 の「関数の定義を後ろに書ける」とも関係しますが、 main 関数を導入する( & 処理を関数に分ける)ことで、抽象度の高いコードと詳細のコードを分けることができます。

おおまかな処理の流れを main 関数に、詳細を別の関数に分けるようにすることで、全体の見通しをよくできます。 たとえば次のようなコードであれば、そのコードでどのような処理が行われているのかを main 関数を見るだけで大まかに把握できます。

def main():
    data = load_data()
    result = process_data(data)
    save_data(result)


def load_data():
    ...


def process_data(data):
    ...


def save_data(result):
    ...


if __name__ == "__main__":
    main()

3. 処理の変更や差し替えがやりやすい

main 関数を使わずコードをベタ書きしていると、処理の変更や一時的な差し替えが必要な場合に、多くの行を書き換えなくてはならず、手間がかかることがあります。

main 関数を定義しておくと、たとえば処理の大部分を変更する必要がある場合には、既存の main 関数を main_old 等にリネームして新たな main 関数を定義するといったことをすれば大幅な変更でもすぐに対応が可能です。

4. テストが書きやすい

main 関数を使わずコードをベタ書きしていると自動テストが書きづらくなります。

5. 変数名の意図しない衝突を防げる

main 関数を使わずコードをベタ書きすると、多くの変数がグローバル変数のような扱いになってしまいます。 結果として、意図しない変数名の重複によるバグの発生や、用済みデータが残ることによる無駄なメモリの使用等が起こりえます。

# 意図しない変数名の重複の例
result = fetch_data()

...

# `calculate()` の結果を表示するための `print()` を追加したが
# 間違えて `calculate()` の前に `print()` を書いてしまった
# ↓
# 本来 `NameError` が起こってすぐに気づくはずだが
# 変数 `result` を上でも使っているのでエラーにならず間違いの発見が遅れる
print(result)
result = calculate()

……このぐらいでしょうか。 細かくあげていくと他にもあげられると思います。

ということで、 Python スクリプトにおいて main 関数を書くことのメリットについてでした。