【Python入門】関数とは?def・引数・戻り値・main関数・if name == “main”まで初心者向けに解説

Python

Pythonでプログラムを書いていると、必ずと言っていいほど登場するのが「関数」です。

例えば、次のようなコードです。

def hello():
    print("Hello, Python!")

hello()

さらに、少し本格的なPythonプログラムを見ると、次のような記述もよく登場します。

def main() -> None:
    print("プログラムを開始します")

if __name__ == "__main__":
    main()

Python初心者の方にとっては、

  • defとは何?
  • 関数を使うメリットは?
  • 引数と戻り値の違いは?
  • def main() -> None:とは?
  • __name__とは?
  • "__main__"とは?
  • なぜ if __name__ == "__main__": と書くの?
  • 毎回書かなければいけないの?

と疑問に思うかもしれません。

ここでは、初心者・初心者エンジニア向けに順番に解説します。

この記事の対象

  • Pythonを勉強し始めた方
  • Pythonの関数について知りたい方
  • defの意味を理解したい方
  • 引数と戻り値について知りたい方
  • def main() -> None:の意味を知りたい方
  • if __name__ == "__main__":の意味を知りたい方
  • 実務で読みやすいPythonコードを書きたい方
スポンサーリンク
スポンサーリンク

関数とは?

関数とは、プログラム内で特定の処理をまとめた再利用可能なコードブロックです。簡単に言うと、特定の処理をひとまとめにした再利用可能なコードです。

関数を使うことで、同じ処理を繰り返し実行する必要がある場合や、大きなプログラムをより小さな部分に分割することができます。

特に、同じような処理を何度も書くことはBugの元になります。そのような場合に関数とすることで簡略化して記述します。

関数の定義と呼び出し

関数は「def」キーワードを使用して定義します。

基本形は次の通りです。

def 関数名():
    処理

例えば、

def hello():
    print("Hello, world!")

と書くことで、helloという名前の関数を作成できます。

関数を実行する場合は、

hello()

と書きます。

完全なコードは次のようになります。

def hello():
    print("Hello, world!")

hello()

実行結果は、

Hello, world!

となります。

引数とは?

関数に値を渡したい場合は「引数」を使います。

例えば、

def hello(name):
    print("Hello, " + name)

hello("Taro")

実行すると、

Hello, Taro

と表示されます。

この場合、

name

が引数です。

呼び出し側から、

"Taro"

という値を関数へ渡しています。

関数に値を渡したい場合は「引数」を使います。

例えば、

def hello(name):
    print("Hello, " + name)

hello("Taro")

実行すると、

Hello, Taro

と表示されます。

この場合、

name

が引数です。

呼び出し側から、

"Taro"

という値を関数へ渡しています。

戻り値とは?

関数で計算した結果を呼び出し元へ返したい場合は、returnを使用します。

例えば、2つの数値を足し算する関数を作ってみます。

def add(a, b):
    return a + b

result = add(10, 20)
print(result)

実行結果は、

30

になります。

ここでは、

return a + b

によって計算結果を呼び出し元へ返しています。

引数と戻り値の関係をまとめると以下になります。

def 関数名(引数1,引数2,...):
 処理
 return 戻り値

引数は必ず指定するものではなく、加えて複数指定するものでもないことが特徴です。また、「戻り値」は関数の処理での結果で返ってくる値を指します。戻り値がない場合はreturnを省略できます。

デフォルト引数

関数の引数にはデフォルト値を設定することもできます。デフォルト引数が指定されている場合、引数が省略された場合にデフォルト値が使用されます。

def test(name="hoge"):
    print("Hello, " + name + "!")

test()         # Hello, hoge!
test("hogehoge")  # Hello, hogehoge!

可変長引数

関数に可変長の引数を受け取る場合、アスタリスク(*)を使って引数を指定します。可変長引数はタプルとして関数内で扱われます。

def test(*numbers):
    for num in numbers:
        print(num)

test(1, 2, 3)        # 1 2 3
test(10, 20, 30, 40) # 10 20 30 40

可変長引数については以下をご参照下さい。

>>>Python初心者が知っておきたい関数-可変長引数-

def main() -> None: とは?

サンプルコードなどを見ていると、次のような書き方を見かけることがあります。

def main() -> None:
    print("Hello, Python!")

if __name__ == "__main__":
    main()

初学者が上記に出くわすと何のおまじない?となると思います。

結論から言うと、これは 型ヒント と呼ばれる書き方です。

-> None は、

この関数は戻り値を返しません

という意味です。

例えば、次の関数は戻り値があります。

def add(a: int, b: int) -> int:
    return a + b

この場合、-> int は「整数を返す関数です」という意味です。

一方で、次のような関数は画面に表示するだけで、値を返していません。

def main() -> None:
    print("処理を開始します")

このように、return で値を返さない関数には -> None と書くことがあります。

型ヒントは必要ということでなく、戻り値があるか?あった場合は何型なのか?が分かりやすいです。言ってしまえば、可読性がある書き方というだけです。

実務で使う場合は重宝しますが、趣味でPythonを使用する分にはこんな書き方もあるんだ程度の認識で良いかと思います。備忘録のため。ここでは紹介しました。

if name == “main“:とは?

Pythonのサンプルプログラムや実務コードでは、次の書き方も頻繁に見かけます。

if __name__ == "__main__":
    main()

初めて見ると、「アンダースコアが多くて難しそう……」と感じるかもしれません。

しかし、意味が分かればそれほど難しくありません。

簡単に言うと、「このPythonファイルが直接実行された場合だけ、以下の処理を実行する」という意味です。

__name__とは?

Pythonでは、それぞれのPythonファイルに

__name__

という特別な変数が用意されています。

例えば、次のプログラムを作ってみます。

print(__name__)

ファイル名を、

sample.py

として直接実行します。

python sample.py

すると、

__main__

と表示されます。

つまり、Pythonファイルを直接実行した場合、

__name__

には、

"__main__"

が入ります。

Python公式ドキュメントでも、トップレベルのスクリプトとして実行されたモジュールでは、__name__ が "__main__" になると説明されています。

if name == “main“:を日本語にすると?

次のコードを、

if __name__ == "__main__":
    main()

日本語のイメージにすると、「もし”このファイルが直接実行されたファイル”であれば、main()を実行する」となります。

より簡単に言えば、

直接実行された?
    ↓
YES
    ↓
main()を実行する

という処理です。

なぜif name == “main“:が必要なの?

ここが最も重要なポイントです。

Pythonでは、別のPythonファイルをimportして利用できます。

例えば、

main.py
calculation.py

という2つのファイルがあるとします。

calculation.pyを次のようにします。

def add(a: int, b: int) -> int:
    return a + b

print("calculation.pyを実行しました")

そして、main.pyから読み込みます。

import calculation

result = calculation.add(10, 20)
print(result)

この場合、calculation.pyをimportしただけなのに、

print("calculation.pyを実行しました")

まで実行されてしまいます。

つまり、「関数だけ使いたかったのに、関係ない処理まで勝手に動いた」ということが起こります。

if name == “main“:を使って防ぐ

そこで、calculation.pyを次のように変更します。

def add(a: int, b: int) -> int:
    return a + b

def main() -> None:
    print("calculation.pyを直接実行しました")

if __name__ == "__main__":
    main()

この状態で、

python calculation.py

と直接実行すると、

calculation.pyを直接実行しました

と表示されます。

一方、

import calculation

と別のプログラムからimportした場合、

main()

は実行されません。

しかし、

calculation.add()

は利用できます。これが、「if __name__ == “__main__”:」を使う大きな理由です。

直接実行とimportの違い

ここは初心者の方が特につまずきやすいため、表で整理します。

実行方法__name__の値main()
python sample.py"__main__"実行される
import sample"sample"実行されない

つまり、「if __name__ == “__main__”:」によって、「直接実行されたときの処理」と「importされたときの処理」を分けることができます。

実際に確認してみよう

次のsample.pyを作ります。

print("__name__ =", __name__)

def hello() -> None:
    print("Hello!")

def main() -> None:
    print("main関数が実行されました")
    hello()

if __name__ == "__main__":
    main()

直接実行します。

python sample.py

実行結果:

__name__ = __main__
main関数が実行されました
Hello!

今度は別ファイルを作ります。

import sample

実行すると、

__name__ = sample

となります。

main()は実行されません。この違いを実際に確認すると、if __name__ == "__main__":の仕組みが理解しやすくなります。

実務ではなぜ使うの?

数行程度のプログラムでは、

print("Hello")

だけでも問題ありません。しかし、実務ではプログラムが大きくなりがちです。

例えば、

main.py
config.py
database.py
network.py
logger.py
sensor.py

のように複数のPythonファイルへ分割することがあります。

そのとき、「import sensor」しただけでセンサー処理が自動実行されたり、「import network」しただけで通信が開始されたりすると困ります。

そこで、

def main() -> None:
    処理

if __name__ == "__main__":
    main()

という構造にします。

これによって、

  • importしただけでは処理を開始しない
  • 直接実行した場合だけ処理を開始する
  • 関数を他のファイルから再利用できる
  • テストしやすくなる
  • プログラムの入口が分かりやすくなる

というメリットがあります。

実務でおすすめの基本形

実務で使用し始める際に、次の形を覚えておくと便利です。

def main() -> None:
    print("プログラムを開始します")
    # メイン処理を書く
    print("プログラムを終了します")

if __name__ == "__main__":
    main()

ただし、main()の中に何百行もの処理を書くのではなく、処理ごとに関数へ分割することが重要です。

例えば、

def initialize() -> None:
    print("初期化します")

def get_data() -> list[int]:
    return [10, 20, 30]

def show_result(data: list[int]) -> None:
    print(data)

def main() -> None:
    initialize()
    data = get_data()
    show_result(data)

if __name__ == "__main__":
    main()

このようにすると、「initialize()」→「get_data()」→「show_result()」というプログラム全体の流れがmain()を見るだけで分かります。

実務では、このような構造にすると保守しやすくなります。

main()の中には「処理の流れ」を書く

特に初心者エンジニアの方におすすめしたい考え方があります。

それは、main()には細かな処理ではなく、プログラム全体の流れを書くという考え方です。

例えば、あまり良くない例です。

def main() -> None:
    # 大量の計算処理
    # ファイル読み込み
    # JSON解析
    # 通信処理
    # ログ処理
    # データ保存
    # さらに大量の処理

これでは、せっかくmain()を作っても読みにくくなります。

処理ごとに関数へ分けます。

def load_config():
    pass

def connect_device():
    pass

def get_data():
    pass

def save_data():
    pass

def main() -> None:
    config = load_config()
    connect_device()
    data = get_data()
    save_data()

こうすると、

設定読み込み
↓
機器接続
↓
データ取得
↓
データ保存

という処理の流れが一目で分かります。

これは、実務でプログラムを読みやすくするうえで非常に重要です。

if name == “main“:は必ず必要?

結論として、必ず必要というわけではありません。

例えば、

print("Hello")

だけの学習用プログラムなら、無理に使う必要はありません。

しかし、

  • プログラムが大きくなってきた
  • 関数が増えてきた
  • 複数ファイルに分割する
  • 他のファイルからimportする
  • テストを書く
  • 業務用ツールを作る
  • FlaskやTkinterなどでアプリを作る
  • Raspberry Piなどで制御プログラムを作る

といった場合には、この書き方を理解しておくと非常に役立ちます。

初心者の段階から、

def main() -> None:
    ...

if __name__ == "__main__":
    main()

という基本形に慣れておくのもおすすめです。

関数を使った実務に近いサンプル

最後に、少し実務に近いサンプルを見てみましょう。

from __future__ import annotations

def read_temperature() -> float:
    """温度を取得するサンプル関数です。"""
    return 25.5

def check_temperature(temperature: float) -> None:
    """温度を判定します。"""
    if temperature >= 30.0:
        print("警告:温度が高くなっています")
    else:
        print("温度は正常です")

def main() -> None:
    print("監視プログラムを開始します")
    temperature = read_temperature()
    print(f"現在温度:{temperature}℃")
    check_temperature(temperature)

if __name__ == "__main__":
    main()

このプログラムでは、それぞれの関数に役割を持たせています。「read_temperature():温度取得」→「check_temperature():温度判定」→「main()」→プログラム全体の処理

このように、処理を小さな関数へ分割し、main()で全体の流れを組み立てると、読みやすく保守しやすいプログラムになります。

まとめ

今回は、Pythonの関数について、基本から

if __name__ == "__main__":

まで解説しました。

重要なポイントを整理すると、次のようになります。

  • 関数は処理をひとまとめにする仕組み
  • defで関数を定義する
  • 引数を使って関数へ値を渡せる
  • returnを使って結果を返せる
  • 型ヒントを使うと関数の用途が分かりやすくなる
  • main()はプログラム全体の処理をまとめるためによく使われる
  • -> Noneは値を返さないことを示す型ヒント
  • __name__はPythonが用意している特別な変数
  • Pythonファイルを直接実行すると__name__は"__main__"になる
  • if __name__ == "__main__":を使うと、直接実行された場合だけ処理を動かせる
  • importされた場合に不要な処理が勝手に実行されるのを防げる

特に初心者エンジニアの方には、次の形を覚えておくことをおすすめします。

def main() -> None:
    # プログラム全体の流れを書く
    pass

if __name__ == "__main__":
    main()

Pythonの学習を始めたばかりの段階では少し難しく見えるかもしれません。

しかし、プログラムが大きくなり、複数ファイルへの分割や関数の再利用を行うようになると、if __name__ == "__main__":の意味が非常に重要になってきます。

単に「おまじない」として覚えるのではなく、「このファイルを直接実行した場合だけ、ここからプログラムを開始するための仕組み」と理解すると良いです。

【おまけ】関数の操作

項目内容
Docstring関数を用いるとき、処理内容に対する説明文があると後から修正したり加えたりするときに便利です。
再帰関数における再帰とは、関数の中で関数を呼び出すことを指します。
関数と引数の関係関数内で使用する要素を引数にすることが可能です。
関数と変数の関係関数における変数にはルールがあります。ローカル変数とグローバル変数を利用することで効率が良いプログラムを作成可能です。
無名関数無名関数とは名前の無い関数を指します。変数に代入して使用することで簡単に使用できます。

その他、関数を用いた使用例

項目内容
任意のリスト内の中央値を求めるプログラムリンク先では任意のリスト内の中央値を求めるプログラムを解説しています。
タイトルとURLをコピーしました