高階関数
高階関数 とは
関数を引数や戻り値として扱う高階関数の考え方を学びます。本レッスンでは、高階関数 の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。
高階関数
Python では、関数自体を「値」として扱えます。数値や文字列と同じように、関数を変数に入れたり、別の関数の引数として渡したりできます。このように 関数を引数として受け取る関数 を 高階関数 (higher-order function) と呼びます。map、filter、sorted(key=...) などが代表例です。
関数は
first-class object(第一級オブジェクト) として扱われます。これはPythonを含む多くのモダンな言語の重要な特徴です。
関数を変数に入れる
まず、関数を変数に代入できることを確認しましょう。
Python
def shout(text):
return text.upper() + "!"
f = shout
print(f("hello"))f = shout で、shout 関数そのものを変数 f に代入しています。f("hello") は shout("hello") と同じです。() を付けると呼び出し、付けなければ関数オブジェクトそのもの、というのが重要な区別です。
関数を引数として渡す
他の関数に関数を渡すこともできます。
Python
def apply(func, value):
return func(value)
def double(x):
return x * 2
print(apply(double, 5))apply の中で func(value) と呼び出しているので、渡した double がそこで実行されます。「処理を引数として渡す」感覚は、初めは新鮮ですが、慣れると非常に強力な道具になります。
標準ライブラリの高階関数
Python 標準ライブラリには高階関数がたくさんあります。次のとおりです。
map(func, iterable)各要素に関数を適用filter(func, iterable)条件を満たす要素だけ残すsorted(iterable, key=func)ソート時のキー関数functools.reduce(func, iterable)累積計算
これらを使いこなせると、for ループで書くより簡潔で意図の伝わるコードになります。
map で全要素を変換
map はリストの各要素に関数を適用して、新しい結果を作ります。
Python
def square(x):
return x * x
nums = [1, 2, 3, 4]
result = list(map(square, nums))
print(result)map の戻り値は map オブジェクトという特別な型なので、リストとして見たいときは list(...) で包みます。
sorted の key にも関数を渡す
sorted の key 引数も関数を受け取る高階関数です。
Python
words = ["apple", "banana", "kiwi"]
print(sorted(words, key=len))len という関数オブジェクトをそのまま渡しています。sorted の中で len(要素) が呼ばれ、その戻り値を比較してソートされます。
動きを追ってみる
高階関数の流れを図にしてみます。
「関数を渡して、要素ごとに呼んでもらう」という形は、ループを自分で書かないで済む書き方です。
lambda との相性
高階関数は lambda と一緒に使うと特に便利です。
Python
nums = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x * x, nums))
print(squared)わざわざ def square(x): return x * x を書かなくても、その場で lambda x: x * x を渡せます。コードが短くなり、意図も読み取りやすくなります。
よくある間違い
- 関数を渡すつもりが、呼び出した結果を渡してしまう (
apply(double(5))のように) - 関数オブジェクトと値を混同する (
funcとfunc()の違い) mapの戻り値をlistで包み忘れて<map object at 0x...>と表示される
Python
def apply(func, value):
return func(value)
# NG: double を呼び出してしまっている
apply(double(5), 10)
# OK: 関数オブジェクトを渡す
apply(double, 5)「
funcは手紙」「func()は手紙を読んだ結果」と覚えると区別しやすくなります。手紙そのものを渡したいのか、中身を渡したいのかで()の有無を決めます。
やってみよう
ここでは、リストを受け取って 全要素を 2 倍にした新しいリスト を返す関数 double_all を書いてみましょう。関数内部で lambda x: x * 2 と map を組み合わせて実装してください。リストとして返す必要があるので list(...) で囲んでください。テストでは double_all([1, 2, 3]) のような形で呼び出されます。
よくある質問
Q. 高階関数とは何ですか?
A. 関数を引数に取る、または関数を返す関数のことです。map / filter / reduce が代表で、コールバックを受け取って汎用化された処理を提供します。「処理の差分だけ渡せる」ため、ボイラープレートが減りコードが宣言的になります。
Q. カリー化はどんな場面で使いますか?
A. 引数を順番に部分適用したいときや、関数合成を綺麗に書きたいときに有効です。例えば add(a)(b) と書ければ add(5) で「5 を足す関数」が作れます。React のイベントハンドラ生成や、設定付きユーティリティ関数を作るのに便利です。
Q. 関数型と OOP はどっちを使うべき?
A. 状態を持つドメインモデルは OOP、データ変換パイプラインは関数型と使い分けるのが現代的です。Java も Stream で関数型を取り入れており、JS も class と高階関数を併用します。完全にどちらかに振らず、適材適所で組み合わせる設計が主流です。
次のレッスン
次は map で全要素を変換 で、関数を引数や戻り値として扱う高階関数の考え方を学びます を学びます。
事前確認 — 進む前に次の 3 つができることを確認しましょう。
- 高階関数 の要点を自分の言葉で説明できる
- このレッスンの最小コード (または操作手順) を見ずに書ける
- 練習問題やクイズで間違えた箇所を読み直して理解した
理解度チェック (30 秒)
Q. 高階関数 とは何か、1 文で説明してください。
A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。
関連レッスン
要件
- double_all 関数を定義する
- map と lambda を使って全要素を 2 倍にする
- list で囲んで新しいリストとして返す
入出力例
test-cases.txt
double_all([1,2,3]) → [2,4,6]
double_all([]) → []
double_all([0,5,-3]) → [0,10,-6]
double_all([7]) → [14]