Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【ITニュース解説】Functional Programming In Python

2025年09月19日に「Dev.to」が公開したITニュース「Functional Programming In Python」について初心者にもわかりやすく解説しています。

作成日: 更新日:

ITニュース概要

関数型プログラミングは、入力値のみで結果が決まる「純粋関数」を使い、状態を変えずに処理を進める手法だ。Pythonでは関数が変数と同じ「第一級オブジェクト」のため、`lambda`で無名関数を定義したり、`map`や`filter`、`reduce`といった高階関数を活用したりして、コードをより簡潔に記述できる。

出典: Functional Programming In Python | Dev.to公開日:

ITニュース解説

関数型プログラミングは、プログラムを「純粋な関数」の評価(計算)の集合として考えるプログラミングの考え方の一つだ。このアプローチでは、プログラムの状態が時間と共に変化する「副作用」を極力排除し、入力値から出力値が一意に定まるような関数を中心にコードを構築する。システムエンジニアを目指す上で、この考え方はコードの予測可能性を高め、保守性を向上させる上で非常に役立つ。

純粋関数とは、その関数の出力が、与えられた入力値のみによって決まり、外部の状態を一切変更しないし、外部の状態にも影響されない関数のことを指す。例えば、与えられた二つの数値を足し算する関数は、入力された数値が同じであれば必ず同じ結果を返し、外部のデータやシステムに影響を与えることはない。このような純粋関数を組み合わせることで、プログラムの各部分が独立して機能し、バグの発生を抑え、テストを容易にすることができる。状態の変更や可変なデータへの依存を避けることで、並行処理や並列処理においても予期せぬ問題が起きにくくなるという利点もある。

Pythonは、その設計思想から関数型プログラミングの概念を強力にサポートしている。その最も基本的な特徴の一つが、「関数がファーストクラスオブジェクトである」ということだ。これは、関数が数値や文字列といった他のデータ型と同じように扱えるという意味だ。具体的には、関数を変数に代入したり、関数の引数として別の関数を渡したり、関数から別の関数を戻り値として返したりすることが可能になる。

例えば、「こんにちは!」と表示するシンプルな関数を定義した場合、その関数名を別の変数に代入し、その変数を通して元の関数を実行できる。これは、文字列を変数に代入するのと全く同じ感覚で関数を扱えるということだ。また、関数自身を他のデータと同じように、print関数で表示することもできる。このとき表示されるのは、関数がメモリ上のどこに存在するかを示す情報だ。

関数を引数として別の関数に渡す場合、渡された関数は「コールバック関数」と呼ばれることがある。これは、ある処理が終わった後に特定の関数を実行してほしい、といったシナリオで使われる。同様に、関数が別の関数を戻り値として返すことも可能だ。例えば、ある関数が、内部で定義した別の関数を返すといったコードは、Pythonで頻繁に見られるパターンだ。この場合、戻り値として得られた関数を変数に格納し、その変数を通して元の内側の関数を実行できる。あるいは、最初の関数の呼び出しの直後に、得られた関数をさらに呼び出すというような連続した呼び出し方も可能だ。

関数が内部の関数を返したとしても、その内部関数が外部関数のスコープで定義されていた変数を記憶し、利用し続けることができる機能がある。これを「クロージャ」と呼ぶ。これは、外部関数が実行を終えても、内部関数がその実行時の環境(変数の値など)を「閉じ込めて」持ち続けるという考え方で、これにより特定の状態を持った関数を作成できるようになる。

関数型プログラミングでは多くの関数を定義するが、中には一度きりしか使わないような小さな関数もある。そのような場合に便利なのが「ラムダ式」だ。ラムダ式は、名前を持たない「匿名関数」をその場で簡潔に定義する方法だ。lambdaキーワードに続けて引数リストと式を書くだけで、シンプルな処理を行う関数を一行で定義できる。例えば、文字列を逆順にする関数や、数値が偶数か奇数かを判定する関数を、その場で名前を付けずに定義してすぐに利用できる。これは、コードをよりコンパクトにし、一時的な処理のためにわざわざ関数を定義する手間を省く。

Pythonの標準ライブラリには、関数型プログラミングのスタイルをサポートする便利な組み込み関数がいくつかある。その一つがmap()関数だ。map()は、リストやタプルなどの「イテラブル」(繰り返し可能なオブジェクト)の各要素に対して、指定された関数を適用し、その結果を新しいイテラブル(通常はリストに変換して使う)として返す。例えば、文字列のリストの各要素を逆順にする関数をmap()に渡せば、元のリストの要素が全て逆順になった新しいリストが生成される。map()は、複数のイテラブルを引数として受け取ることもでき、その場合、指定された関数は各イテラブルから対応する要素を一つずつ受け取って処理を行う。

次にfilter()関数だ。filter()は、イテラブルの要素の中から、指定された条件(関数がTrueを返す要素)に合致するものだけを抽出して、新しいイテラブルを生成する。例えば、数値のリストから100より大きい数値だけを取り出したい場合、100より大きいかどうかを判定する関数をfilter()に渡すことで、条件に合う要素だけが残された新しいリストを得ることができる。

最後にreduce()関数がある。reduce()は、functoolsモジュールからインポートして使う。これは、イテラブルの要素を「二つずつ」取り出して指定された関数に適用し、その結果を次の計算に利用するという操作を繰り返すことで、最終的に単一の結果を生成する。例えば、数値のリストの全ての要素を合計したい場合、reduce()に関数(例えば足し算)とリストを渡すと、リストの先頭から順に二つの要素が足し合わされ、その結果と次の要素が足し合わされる、という処理を繰り返して最終的な合計値が得られる。また、reduce()には初期値を指定することも可能で、その場合、計算はその初期値から開始される。

これらの関数型プログラミングの概念とPythonの機能は、より簡潔で理解しやすく、テストしやすいコードを書くための強力なツールとなる。システム開発において、複雑な問題をシンプルに分解し、それぞれの部分を独立した純粋関数として実装することで、信頼性が高く、保守が容易なシステムを構築する手助けとなるだろう。

関連コンテンツ