関数

【Python】map関数の使い方の基本 ~要素への関数適用~

【Python】map関数の使い方の基本 ~リスト要素への関数適用~
naoki-hn

Python の組み込み関数の map 関数を使って要素へ関数を適用する方法を解説します。

map 関数で要素へ関数を適用する

map 関数は、関数と処理対象のイテラブルを受け取って、イテラブルの各要素に関数を適用した結果を返す Python の組み込み関数です。

このように引数に関数を受け取る関数は高階関数と言います。for 文で処理しても同じ処理ができますが、繰り返し処理を書かずにシンプルに記載できる点がメリットです。

map 関数は、関数型プログラミング言語において中心的な関数です。Python はマルチパラダイムの言語と言われているため、厳密ではありませんが関数型のプログラミングスタイルもサポートしており、map 関数が組み込み関数として利用できます。

本記事では、リストの要素へ関数を適用する例を用いて、map 関数の使い方の基本を紹介します。

map 関数と同様に関数型プログラミングに関連のある関数として filter 関数、reduce 関数、partial 関数があります。以下ページも参考にしてください。

map 関数の基本的な使い方

map 関数の基本的な構文は以下のようになります。

result = map(関数, イテラブル)

複数の引数を取る関数を指定する場合には、以下のようにイテラブルを列挙して指定することができます。

result = map(関数, イテラブル1, イテラブル2, ...)

map 関数では、イテラブルの各要素に関数を適用した結果のイテレータを返却します。イテレータは値を逐次取り出せるオブジェクトで、nextを用いることで順に関数を適用した値を取り出したり、for 文で使用したりすることができます。後述の例でも見ますが、list(map(関数, イテラブル)) のようにすることでリストに変換して取得することも可能です。

また、map(関数, イテラブル1, イテラブル2, ...)というように複数のイテラブルを渡す場合には、関数は引数としてイテラブルの数だけ受け取れる必要があります。

イテレータの基本は以下を参考にしてください。

イテレータ(iterator)の基本

基本的な使い方

map 関数の基本的な使い方を以下の例を用いて見ていきましょう。

def square(x):
    """値を2乗する"""
    return x**2


if __name__ == "__main__":
    tmp_list = [1, 2, 3, 4, 5]

    # map関数を適用し、イテレータを取得
    result = map(square, tmp_list)
    print(result, "\n")

    # nextで1要素ずつ結果データを取得
    print(next(result))
    print(next(result))
    print(next(result))
    print(next(result))
    print(next(result))
【実行結果】
<map object at 0x0000018E82BC2A70> 

1
4
9
16
25

上記の例では、受け取った値を 2 乗する square という関数が定義されており、tmp_list の各要素に適用しています。

map 関数を呼び出している部分では「map(square, tmp_list)」というように関数と処理対象のリストを渡しています。ここでポイントは、関数を渡す際に () がないことです。関数は square(2) のように () で引数を指定すると関数を実行することを意味しますが、() がない場合は関数そのものを表します。map 関数は、受け取った square という関数を内部で実行しているわけです。

map 関数の返却値は「map object」となっていますが、これはイテレータの一種です。next 関数を使用することで次の要素を順番に取得することができます。この例では、tmp_list の要素それぞれを2乗した結果が順に取得されていることが分かります。

注意点

上記例で next(result) を追加して再度実行すると StopIteration 例外が発生します。これはイテレータがもう要素を持たない場合に発生する例外です。StopIterationfor ループ等の繰り返しの終了を判断するために使用されています。

【実行結果】
Traceback (most recent call last):
...(省略)...
StopIteration

リストやタプルで取得する場合

map 関数の返却値はイテレータであるため、以下のように listtuple に変換することができます。

def square(x):
    """値を2乗する"""
    return x**2


if __name__ == "__main__":
    tmp_list = [1, 2, 3, 4, 5]

    # map関数を適用し、リストで取得
    result_list = list(map(square, tmp_list))
    print(result_list)

    # map関数を適用し、タプルで取得
    result_tuple = tuple(map(square, tmp_list))
    print(result_tuple)
【実行結果】
[1, 4, 9, 16, 25]
(1, 4, 9, 16, 25)

複数イテラブルを指定する場合

map 関数は複数のイテラブルを受け取り、それらに対してまとめて関数を適用することができます。以下の例では、make_variable_set という関数が 3 つの引数を受け取り、それらをタプルとして返す動作をします。

def make_variable_set(x, y, z):
    """各引数を並べたタプルを返却する"""
    return x, y, z


if __name__ == "__main__":
    nums1 = [1, 2, 3]
    nums2 = [4, 5, 6]
    nums3 = [7, 8, 9]

    # map関数で複数のイテラブルを渡す
    # 関数側もイテラブルの数だけの引数を受け取れる必要がある
    result = list(map(make_variable_set, nums1, nums2, nums3))
    print(result)
【実行結果】
[(1, 4, 7), (2, 5, 8), (3, 6, 9)]

この結果を見ると、3 つのリストの各要素が関数によってタプルとしてまとめられて返されていることが確認できます。

注意点

map(関数, イテラブル1, イテラブル2, ...) というように複数のイテラブルを渡す場合、関数は指定するイテラブルの数だけ引数を受け取ることができるように設計されている必要があります。

複数のイテラブルの要素数が異なる場合

map 関数を使用する際、複数のイテラブルを指定することができますが、それらの要素数が異なる場合の挙動に注意が必要です。

具体的には、map 関数は、最も短いイテラブルの要素数に合わせて処理を行います。これは最も短いイテラブルが終了した時点で、他のイテラブルの残りの要素は無視されることを意味します。

def make_variable_set(x, y, z):
    """各引数を並べたタプルを返却する"""
    return x, y, z


if __name__ == "__main__":
    nums1 = [1, 2, 3]
    nums2 = [4, 5, 6, 7, 8, 9]
    nums3 = [10, 11, 12, 13, 14]

    # map関数で複数のイテラブルを渡す
    # 最も短いイテラブルが消費されたら終了
    result = list(map(make_variable_set, nums1, nums2, nums3))
    print(result)
【実行結果】
[(1, 4, 10), (2, 5, 11), (3, 6, 12)]

この例では、3 つの要素を使用していますが、最も短いイテラブルである nums1 に合わせて処理が行われるため、nums2789nums31314 については結果に含まれていないことが分かります。

ラムダ関数(無名関数)と組み合わせる場合

map 関数は、ラムダ関数(無名関数)と組み合わせることで、より手軽に要素に対して関数を適用することができます。ラムダ関数は、関数定義を def で定義することなく、その場で作れるもので関数型プログラミングでは中核の概念です。

square 関数をラムダ関数にして map 関数で使う例を見てみましょう。

tmp_list = [1, 2, 3, 4, 5]

# map関数を適用し、リストで取得
result = list(map(lambda x: x**2, tmp_list))
print(result)

# map関数を適用し、タプルで取得
result = tuple(map(lambda x: x**2, tmp_list))
print(result)
【実行結果】
[1, 4, 9, 16, 25]
(1, 4, 9, 16, 25)

これまでの例で square と関数を指定していた部分に「lambda x: x**2」というラムダ関数を指定しています。結果は square 関数を使った場合と同じす。

ラムダ関数は無名関数ともいわれる通り、関数名はありませんが、そのものが関数として扱われるため、map 関数に渡すことでリストの各要素に関数を適用できます。

ラムダ関数の基本については以下を参考にしてください。

ラムダ(lambda)関数:無名関数の使い方

まとめ

Python の組み込み関数である map 関数を使って要素へ関数を適用する方法を解説しました。

map 関数は、関数と処理対象のイテラブルを受け取って、イテラブルの各要素に関数を適用した結果を返す Python の組み込み関数です。map 関数は他の関数型プログラミング言語でも中心的な関数で Python でも使用できます。

map 関数は for 文を用いなくてもシンプルに関数の適用ができることが特徴です。非常に強力な機能ではありますが、map 関数の適用が常に最適な選択というわけではありません。

場合によっては for 文で書いた方が可読性が上がる可能性もあります。目的に応じて適切に方法を選択できるよう map 関数の使い方を理解しておくようにしましょう。

ソースコード

上記で紹介しているソースコードについては GitHub にて公開しています。参考にしていただければと思います。

あわせて読みたい
【Python Tech】プログラミングガイド
【Python Tech】プログラミングガイド
ABOUT ME
ホッシー
ホッシー
システムエンジニア
はじめまして。当サイトをご覧いただきありがとうございます。 私は製造業のメーカーで、DX推進や業務システムの設計・開発・導入を担当しているシステムエンジニアです。これまでに転職も経験しており、以前は大手電機メーカーでシステム開発に携わっていました。

プログラミング言語はこれまでC、C++、JAVA等を扱ってきましたが、最近では特に機械学習等の分析でも注目されているPythonについてとても興味をもって取り組んでいます。これまでの経験をもとに、Pythonに興味を持つ方のお役に立てるような情報を発信していきたいと思います。どうぞよろしくお願いいたします。

※キャラクターデザイン:ゼイルン様
記事URLをコピーしました