見出し画像

Pythonの関数型プログラミング徹底解説


関数型プログラミングの概要

関数型プログラミングとは、コードのすべての部分が不変で、純粋関数で構成されるスタイルを指します。純粋関数とは、他の関数に依存せず、同じ入力が与えられると常に同じ出力を生成する関数です。

また、関数型プログラミングは、ある関数を別の関数の引数として渡すことができ、また関数を返すこともできるという特徴があります。

純粋関数の例

例えば、リスト内の要素の値を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

いいなと思ったら応援しよう!