【Python】レッスン3-4:高階関数を理解しよう

一つ前のLessonではスコープの概念について学習しました。
今回は高階関数について見ていきます。
Lesson1:基礎文法編
Lesson2:制御構造編
Lesson3:関数とスコープ編
・Lesson3-1:関数の基本を理解しよう
・Lesson3-2:関数の戻り値とデフォルト引数を理解しよう
・Lesson3-3:スコープの概念を理解しよう
・Lesson3-4:高階関数を理解しよう ◁今回はココ
・Lesson3-5:無名関数を理解しよう
・練習問題3-1:丁半賭博ゲームを作ろう
・練習問題3-2:石取りゲームを作ろう
Lesson4:データ構造編
Lesson5:オブジェクト指向編
次のステップ:Python基礎習得者にお勧めの道5選(実務or副業)
高階関数の基本|関数を値として渡す・返す考え方
高階関数とは、関数を引数として受け取る、あるいは関数を戻り値として返す関数のことです。
関数を“値(オブジェクト)”として扱える性質を活かし、振る舞いを後から差し替えたり、処理の流れを組み合わせたりできます(詳細は本文で丁寧に解説します)。
「関数を変数に代入して渡すには?」「戻り値として関数を返すと何が嬉しい?」といった疑問に、短い実例で答えていきます。
さっそく本文へ進み、手を動かしながら高階関数の基礎を体得しましょう。
高階関数とは|引数や戻り値に関数を使う方法
Pythonでは関数は「ファーストクラスオブジェクト」として扱われており、他のオブジェクトと同じように操作が可能です。
これによって関数を動的に操作したり、プログラムの中で柔軟に利用することができます。
関数を変数に代入する例
まずは関数を変数に代入して使う例を紹介します。
def greet(name): # 関数greetの定義 return f"Hello, {name}!" greet_var = greet # 関数greetを変数greet_varに代入 # 関数を呼び出す print(greet_var("Alice")) # 変数greet_var( = 関数greet)に引数Aliceを渡して呼出しして出力
このコードを実行すると以下のように出力されます。
Hello, Alice!
この例では、greet
という関数をgreet_var
という変数に代入しています。
この時点で変数greet_var
と関数greet()
は同じものとなり、変数greet_var
を使って挨拶の出力ができるようになります。
このように関数はそのまま変数に代入でき、変数経由で関数を呼び出すことが可能です。
関数を他の関数の引数にする例
次に、関数を他の関数の引数として渡す例を紹介します。
def greet(name): # 関数greetの定義 return f"Hello, {name}!" def call_function(func, name): # 2つの仮引数を持つ関数call_functionの定義 return func(name) # 引数として関数を渡す print(call_function(greet, "Bob")) # 関数call_functionの実引数として関数greetを渡す
このコードを実行すると以下のように出力されます。
Hello, Bob!
この例では、greet
関数をcall_function
という別の関数の引数として渡しています。
call_function
は受け取った関数を実行し、結果を返します。
このように関数を引数として他の関数に渡すことで、動的に関数を実行することが可能になります。
関数の参照と呼び出しの違い|() の有無で何が変わる
関数を呼び出す際に、関数名の後に()
がある場合とない場合で挙動が異なります。
以下にその違いを説明します。
関数名の後に()
がある場合|命令
関数名の後に括弧を記載するとその関数が実行され、結果が返されます。
つまり()
を使うことで、その場で関数を呼び出し、関数の戻り値を取得します。
# 関数を定義 def hello(): return "Hello, World!" # 関数を実行 print(hello()) # hello()は()があるので、関数helloが実行される
上記の例ではhello()
の()
によって関数が実行され、その戻り値である”Hello, World!”が出力されます。
関数名の後に()
がない場合|オブジェクト
括弧を付けずに関数を記載すると、その関数自体がオブジェクトとして扱われ、実行されません。
関数を変数に代入したり、他の関数に引数として渡すためには、この状態であることが必要です。
# 関数を定義 def hello(): return "Hello, World!" # 関数自体を参照 func_var = hello # ()が無いのでhelloは関数オブジェクトとして扱われ、変数に代入される print(func_var) # 実行結果: <function hello at 0x...>
上記の例ではhello
に()
が付いていないため関数は実行されず、そのオブジェクトがfunc_var
に代入されます。
まとめ|関数を値として扱い、差し替えて再利用しよう
ここまでで、高階関数=関数を引数として受け取る/戻り値として返す関数であること、そして関数を値(オブジェクト)として扱えるという前提を確認しました。
この学習により、処理の差し替えや共通化がしやすくなり、同じ枠組みで振る舞いだけを入れ替える再利用性の高い関数設計ができるようになります。
意図せず実行してしまう/参照できていない、といった混乱も減り、テストしやすく読みやすいコードに近づきます。
まずは小さな処理で、受け取る関数を変えて挙動の違いを比べるところから続けてみてください。
関数を値として扱える感覚が定着するほど、書ける表現は広がっていきます。
- サイト改善アンケート|ご意見をお聞かせください(1分で終わります)
-
本サイトでは、みなさまの学習をよりサポートできるサービスを目指しております。
そのため、みなさまの「プログラミングを学習する理由」などをアンケート形式でお伺いしています。1分だけ、ご協力いただけますと幸いです。
【Python】サイト改善アンケート
練習問題:高階関数を使ってみよう
この記事で学習した「高階関数」を復習する練習問題に挑戦しましょう。
問題|関数の受け渡しによる加算プログラムを作ろう
2つの数を加算する関数を変数に代入し、その変数を使って関数を呼び出してみましょう。
さらに、その関数を別の関数の引数として渡して、関数を動的に実行するようにしましょう。
以下の要件に従ってコードを完成させてください。
- 関数
add_numbers(a, b)
を定義し、2つの数の和を返す。 add_numbers
をadd_var
という変数に代入し、add_var
を通して関数を呼び出して結果を表示する。- 関数
call_function(func, a, b)
を定義し、受け取ったfunc
をa
とb
で呼び出して結果を返す。 call_function
にadd_var
を渡し、結果を表示する。
ただし、以下のような実行結果となるコードを書くこと。
30 40
ヒント|難しいと感じる人だけ見よう
1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。
- ヒント1【コードの構成を見る】
-
正解のコードは上から順に以下のような構成となっています。
1:加算関数を定義し、関数そのものを変数に入れて呼び出すパート
・2つの引数を受け取り、合計を返す関数を用意する(画面表示は関数の外で行う)。
・関数を変数に入れるときは、関数名の後ろに丸かっこを付けない(参照になる)。
・実行したいときは、変数名の後ろに丸かっこを付けて引数を渡す。
・表示は、計算結果をそのまま出力して実行結果例と一致させる。2:受け取った関数を引数で実行し、結果を返す「高階関数」を使うパート
・受け取る引数は「関数」「数値」「数値」の3つ。
・本体では「受け取った関数」を「2つの数値」で呼び出し、その戻り値を返す。
・先に作った変数に入った関数を、そのまま関数引数として渡す。
・出力は呼び出し側で行い、実行結果例の数値と順序に合わせる。
- ヒント2【穴埋め問題にする】
-
以下のコードをコピーし、コメントに従ってコードを完成させて下さい。
# 関数の定義。2つの数の和を計算する関数 def add_numbers(a, b): return a + b # 関数を変数に代入する(関数の受け渡しの例) '''(穴埋め)関数 add_numbers を変数 add_var に代入する行を書く''' # 変数に代入された関数を使って2つの数を加算して表示 print(add_var(10, 20)) # 実行結果: 30 # 関数を引数として別の関数に渡す例 def call_function(func, a, b): # 渡された関数を呼び出し、その結果を返す return '''(穴埋め)'''(a, b) # call_functionを使って、add_var関数を引数として渡す print(call_function('''(穴埋め)''', 15, 25)) # 実行結果: 40
このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。
解答例|関数の受け渡しによる加算プログラム
例えば以下のようなプログラムが考えられます。
- 正解コード
-
# 関数の定義。2つの数の和を計算する関数 def add_numbers(a, b): return a + b # 関数を変数に代入する(関数の受け渡しの例) add_var = add_numbers # 変数に代入された関数を使って2つの数を加算して表示 print(add_var(10, 20)) # 実行結果: 30 # 関数を引数として別の関数に渡す例 def call_function(func, a, b): # 渡された関数を呼び出し、その結果を返す return func(a, b) # call_functionを使って、add_var関数を引数として渡す print(call_function(add_var, 15, 25)) # 実行結果: 40
解答例の解説|関数の受け渡しによる加算プログラムの考え方
解答例の詳細解説は以下の通りです。
- 詳細解説
-
加算関数を定義し、関数そのものを変数に入れて呼び出すパート
# 関数の定義。2つの数の和を計算する関数 def add_numbers(a, b): return a + b # 関数を変数に代入する(関数の受け渡しの例) add_var = add_numbers # 変数に代入された関数を使って2つの数を加算して表示 print(add_var(10, 20)) # 実行結果: 30
ここでは2つの数を受け取り、その合計を返す小さな関数を用意します。
次に、関数名そのものを別の変数に入れ替えて持ち運び、変数経由で実行して結果を表示します。
ポイントは「関数も値として扱える」ことと、関数名の後ろに丸かっこを付けたときだけ実行され、付けないと“関数そのもの”を指すという区別です。
これが理解できると、関数の差し替えや使い回しがぐっと簡単になります。受け取った関数を引数で実行し、結果を返す「高階関数」を使うパート
# 関数を引数として別の関数に渡す例 def call_function(func, a, b): # 渡された関数を呼び出し、その結果を返す return func(a, b) # call_functionを使って、add_var関数を引数として渡す print(call_function(add_var, 15, 25)) # 実行結果: 40
ここでは関数を受け取り、その関数に値を渡して実行し、計算結果を返す“受け口”を用意します。
ポイントは「関数も値として引き回せる」ことです。
受け取ったのが関数そのものなら、好きなタイミングで呼び出して結果を返せます。
先ほど変数に入れておいた関数も、同じ「関数の値」なのでそのまま渡せます。
これにより処理の「中身」だけを差し替えて、同じ枠組みで動かせるようになります。
高階関数の疑問解消|FAQと用語のまとめ
初心者がつまずきやすいポイントをFAQとしてまとめ、またよく使う専門用語をわかりやすく整理しました。
理解を深めたいときや、ふと疑問に感じたときに役立ててください。
FAQ|高階関数に関するよくある質問
- Q1. 関数を引数として渡すと何ができるのですか?
-
関数を引数にすることで、処理の一部を柔軟に切り替えることができ、汎用性の高い関数を作成できます。コールバック関数や関数の委譲などに使われます。
- Q2. Pythonでは関数もオブジェクトですか?
-
はい。Pythonでは関数もファーストクラスオブジェクトとして扱われるため、変数に代入したり、他の関数に渡したりすることが可能です。
- Q3. 関数をリストに格納することはできますか?
-
可能です。複数の関数をリストに入れてループ処理することで、動的な関数呼び出しや処理の順次実行が実現できます。
Python用語集|高階関数に関する用語一覧
今回の記事で出てきた用語・関数などを一覧で紹介します。
このサイトに出てくる 全てのPython用語をまとめた用語集 も活用してください。
Python用語 | 定義・使い方の概要 | 解説記事へのリンク |
---|---|---|
高階関数 | 関数を引数として受け取ったり、戻り値として返したりできる関数。map() や sorted() などが該当 | 本記事 |
オブジェクト | データとその振る舞い(関数)をひとまとめにした構造。Pythonではすべてがオブジェクトである | Lesson5-1 |
ファーストクラスオブジェクト | 関数やデータが他の値と同様に変数に代入でき、引数や戻り値として扱える性質。Pythonの関数はこれに該当 | 本記事 |