関数型プログラミングの概要
関数型プログラミングとは、コードのすべての部分が不変で、純粋関数で構成されるスタイルを指します。純粋関数とは、他の関数に依存せず、同じ入力が与えられると常に同じ出力を生成する関数です。
また、関数型プログラミングは、ある関数を別の関数の引数として渡すことができ、また関数を返すこともできるという特徴があります。
純粋関数の例
例えば、リスト内の要素の値を2倍にするには、以下の関数を使用できます:
def multiply_2(list):
for index in range(0, len(list)):
list[index] *= 2
return list
このコードは純粋関数の形式ではないことに注意する必要があります。なぜなら、リスト内の要素の値が変更されるからです。multiply_2()
関数を複数回呼び出すと、毎回結果が異なります。
multiply_2()
を純粋関数にするには、新しいリストを作成して返す必要があります。次のように:
def multiply_2_pure(list):
new_list = []
for item in list:
new_list.append(item * 2)
return new_list
関数型プログラミングの利点と欠点
関数型プログラミングの利点は主に、純粋関数と不変の特性により、プログラムがより堅牢になり、デバッグとテストが容易になることにあります。欠点は主に、制約が多く、記述が難しいことです。
純粋な関数型プログラミング言語(例えばScala)では、書かれた関数内に変数が存在しません。そのため、入力が決まれば出力も決まることが保証されます。変数の使用を許すプログラミング言語では、関数内の変数の状態が不確定なため、同じ入力でも異なる出力が得られる場合があります。
Pythonは変数の使用を許すため、純粋な関数型プログラミング言語ではありません。Pythonは関数型プログラミングを部分的にサポートしており、主にmap()
、filter()
、reduce()
の3つの関数があり、通常はlambda
匿名関数と一緒に使用されます。次に、これら3つの関数の使い方を順に紹介します。
Pythonの関数型プログラミングサポート関数
Pythonのmap()関数
map()
関数の基本構文は以下の通りです:
map(function, iterable)
ここで、function
パラメータは渡される関数を表し、組み込み関数、ユーザー定義関数、またはlambda
匿名関数であってもよいです。iterable
は1つ以上の反復可能なオブジェクト、例えばリスト、文字列などを表します。
map()
関数の機能は、反復可能なオブジェクト内の各要素に対して指定された関数を呼び出し、map
オブジェクトを返すことです。
この関数はmap
オブジェクトを返すため、直接出力することはできません。for
ループやlist()
関数を通じて表示することができます。
[例1] リスト内の各要素を2倍する
listDemo = [1, 2, 3, 4, 5]
new_list = map(lambda x: x * 2, listDemo)
print(list(new_list))
実行結果は:
[2, 4, 6, 8, 10]
[例2] 複数の反復可能なオブジェクトをmap()関数のパラメータとして渡す
listDemo1 = [1, 2, 3, 4, 5]
listDemo2 = [3, 4, 5, 6, 7]
new_list = map(lambda x,y: x + y, listDemo1,listDemo2)
print(list(new_list))
実行結果は:
[4, 6, 8, 10, 12]
map()
関数は直接C言語で書かれており、実行時にPythonインタープリタを介して間接的に呼び出す必要がなく、内部的に多くの最適化が行われています。したがって、他の方法と比較して、この方法は最も高い実行効率を持っています。
Pythonのfilter()関数
filter()
関数の基本構文は以下の通りです:
filter(function, iterable)
この形式では、funcition
パラメータは渡される関数を表し、iterable
は反復可能なオブジェクトを表します。
filter()
関数の機能は、function
関数を使用してiterable
内の各要素を判断し、True
またはFalse
を返すことです。最後に、True
を返す要素が新しい反復可能なコレクションにまとめられます。
[例3] リスト内のすべての偶数を返す
listDemo = [1, 2, 3, 4, 5]
new_list = filter(lambda x: x % 2 == 0, listDemo)
print(list(new_list))
実行結果は:
[2, 4]
[例4] filter()関数が複数の反復可能なオブジェクトを受け取る
listDemo = [1, 2, 3, 4, 5]
new_list = map(lambda x,y: x-y>0,[3,5,6],[1,5,8] )
print(list(new_list))
実行結果は:
[True, False, False]
Pythonのreduce()関数
reduce()
関数は通常、コレクションに対していくつかの累積演算を行うために使用されます。その基本構文は:
reduce(function, iterable)
ここで、function
は必ず2つのパラメータを持つ関数であり、iterable
は反復可能なオブジェクトを表します。
Python 3.xではreduce()
関数が削除され、functools
モジュールに移動しているため、この関数を使用する前にはfunctools
モジュールをインポートする必要があることに注意してください。
[例5] リスト内の要素の積を計算する
import functools
listDemo = [1, 2, 3, 4, 5]
product = functools.reduce(lambda x, y: x * y, listDemo)
print(product)
実行結果は:
120
まとめ
一般的に、コレクション内の要素に対して何らかの演算を行う場合、演算が非常に単純なもの、例えば加算、累積などの場合は、まずmap()
、filter()
、reduce()
を検討する必要があります。また、データ量が非常に大きい場合(例えば機械学習のアプリケーションで)は、関数型プログラミングの表現が通常好まれます。なぜなら、その効率が高いからです。
もちろん、データ量が大きくない場合は、for
ループなどの方法も使用できます。ただし、コレクション内の要素に対してより複雑な演算を行う必要がある場合は、コードの読みやすさを考慮して、通常はfor
ループが使用されます。
Leapcell: 次世代のサーバレス・プラットフォーム、Webホスティング、非同期タスク、Redis用
最後に、Pythonアプリをデプロイするための最高のプラットフォームをおすすめします:Leapcell
1. 多言語対応
- JavaScript、Python、Go、またはRustで開発できます。
2. 無制限のプロジェクトを無料でデプロイ
- 使用量に応じてのみ課金 — リクエストがなければ料金はかかりません。
3. 圧倒的なコスト効率
- 使い放題で、アイドル時の課金はありません。
- 例:25ドルで平均応答時間60msで694万回のリクエストをサポートできます。
4. ストリームライン化された開発者体験
- 直感的なUIで簡単にセットアップできます。
- 完全自動化されたCI/CDパイプラインとGitOps統合。
- アクション可能な洞察のためのリアルタイムメトリクスとロギング。
5. 簡単なスケーラビリティと高性能
- 高い並行処理を簡単に処理できる自動スケーリング。
- オペレーションのオーバーヘッドはゼロ — 構築に集中できます。
LeapcellのTwitter:https://x.com/LeapcellHQ