高階関数

生田 陸人
LuaGate エンジニア / 現役エンジニア
編集 LuaGate編集部

高階関数 とは

関数を引数や戻り値として扱う高階関数の考え方を学びます。本レッスンでは、高階関数 の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。

高階関数

Python では、関数自体を「値」として扱えます。数値や文字列と同じように、関数を変数に入れたり、別の関数の引数として渡したりできます。このように 関数を引数として受け取る関数高階関数 (higher-order function) と呼びます。mapfiltersorted(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 にも関数を渡す

sortedkey 引数も関数を受け取る高階関数です。

Python

words = ["apple", "banana", "kiwi"] print(sorted(words, key=len))

len という関数オブジェクトをそのまま渡しています。sorted の中で len(要素) が呼ばれ、その戻り値を比較してソートされます。

動きを追ってみる

高階関数の流れを図にしてみます。

diagram (will load when visible)

「関数を渡して、要素ごとに呼んでもらう」という形は、ループを自分で書かないで済む書き方です。

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)) のように)
  • 関数オブジェクトと値を混同する (funcfunc() の違い)
  • 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 * 2map を組み合わせて実装してください。リストとして返す必要があるので 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 つができることを確認しましょう。

  1. 高階関数 の要点を自分の言葉で説明できる
  2. このレッスンの最小コード (または操作手順) を見ずに書ける
  3. 練習問題やクイズで間違えた箇所を読み直して理解した

理解度チェック (30 秒)

Q. 高階関数 とは何か、1 文で説明してください。

この章のポイント

A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。

関連レッスン

要件

  1. double_all 関数を定義する
  2. map と lambda を使って全要素を 2 倍にする
  3. 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]

ヒント

main.py
main.py
学習モード

メモ

高階関数

⌘S で保存