関数

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

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

Pythonのラムダ(lambda)関数ラムダ式無名関数とも呼ばれる)の使い方について解説します。

ラムダ(lambda)関数:無名関数

Pythonでは、関数を一つの文で表現することができるラムダ(lambda)関数を使うことができます。式のように使えることからラムダ式、関数名がなく使用できることから無名関数とも呼ばれます。

ラムダ関数は、関数型言語の領域で話が出てくるものですが、Pythonでもラムダ関数は使用することができ、関数型言語のようなスタイルのプログラミングをすることができます。このような特徴のためPythonはマルチパラダイムな言語と呼ばれることがあります。

他にもジェネレータ、高階関数、デコレータ、クロージャ等、関数型プログラミングに関連する仕組みもPythonでは実現できます。ただし、Haskellのような純粋関数型言語ではないため、一貫した関数型プログラミングをするのにはPythonは向いていないのかなと思います。

さて、ラムダ関数を使うことのメリットとしては、以下のようなことがあります。

  • 小さな関数を全てdefで宣言する必要がない
  • 関数名の衝突を考慮する必要がない
  • コードがシンプルになる
  • 高階関数の引数として使用できる

本記事では、ラムダ関数を使用する方法について例を使いながら説明をしていきます。

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

ラムダ関数は、以下のように定義します。式のように記載できることからラムダ式と呼ばれたり、関数名となる部分がないことが無名関数と言われたりもします。

ラムダ関数(ラムダ式、無名関数)
lambda 引数1, 引数2, … : 返却値の計算式

基本的な使用方法

以下の簡単な例を使って、ラムダ関数の使い方を見ていきましょう。

# lambda function
func = lambda val1, val2: val1 * 2 + val2 * 2

print(type(func))
print(func(1, 2))
print(func(3, 4))
【実行結果】
<class 'function'>
6
14

上記例では、引数にval1, val2という二つの引数をとり、それぞれを2倍したものを返却するようなラムダ関数を作成しています。

ラムダ関数の返却する値をtypeで表示していますが<class ‘function’>とあるように関数(function)クラスのオブジェクトです。

このようにPythonでは関数も一つのオブジェクトとして扱うことができます。関数オブジェクトについては、上記例のように()で引数を渡すことで後から関数を実行して値を取得することができます。

ラムダ(lambda)関数を使用することのメリット

ラムダ関数の簡単な使い方を紹介しましたが、defで関数定義しても同じではないかと思うかもしれません。その通りなのですが、ラムダ関数のメリットの一つとして、小さな関数をシンプルに表現して使用できるといったことがあげられます。以下のような例を考えてみます。

def sum_func_value(val_list1, val_list2, func):
    ret = []
    for v1, v2 in zip(val_list1, val_list2):
        ret.append(func(v1, v2))
    return ret


def main():
    l1 = [1, 2, 3, 4, 5]
    l2 = [6, 7, 8, 9, 10]

    ret_list1 = sum_func_value(l1, l2, lambda val1, val2: val1 + val2)
    print(f'ret_list1 = {ret_list1}')

    ret_list2 = sum_func_value(l1, l2, lambda val1, val2: 2 * val1 + 2 * val2)
    print(f'ret_list2 = {ret_list2}')

    ret_list3 = sum_func_value(l1, l2, lambda val1, val2: 3 * val1 + 3 * val2)
    print(f'ret_list3 = {ret_list3}')


if __name__ == '__main__':
    main()
【実行結果】
ret_list1 = [7, 9, 11, 13, 15]
ret_list2 = [14, 18, 22, 26, 30]
ret_list3 = [21, 27, 33, 39, 45]

この例の、sum_func_value関数は、受け取った二つのリストの各要素に対して、funcで指定される関数で処理した結果を返却する関数です。

この例では、呼び出し元でfuncの仮引数に渡す部分をラムダ関数で書いています。1回目の呼び出しは各要素をそのまま足し算、2回目の呼び出しは2倍して足し算、3回目は3倍して足し算というようなラムダ関数を指定しています。

もし、defですべて関数を定義するとラムダ関数で指定している1倍、2倍、3倍となるような関数を作らないといけません。ではさらに4倍、5倍、…という結果が欲しくなったら?と考えると関数名を考えるのも面倒です。このように小さな関数を多く使う場合等にはラムダ関数は便利です。

また、例ではラムダ関数をsum_func_valueの引数として関数に渡しています。つまり、sum_func_valueは関数を引数として受け取る高階関数となっています。このように関数を引数として扱うのは関数型プログラミングの特徴で、ラムダ関数の使い方のよくある例です。

よくある使用例:リストのソート条件をラムダ関数で指定する

ラムダ関数はなかなか使いどころに悩むものかと思いますが、よく使用される場面があります。それがリストをソートする場合です。

リストのソートに関する説明ページ内にて「lambda関数を用いたkeyの指定方法」ということでラムダ関数を使用したソートの説明をしていますので参考にしていただければと思います。

まとめ

Pythonのラムダ(lambda)関数ラムダ式無名関数とも呼ばれる)の使い方について解説しました。

ラムダ関数は、小さな関数を宣言する必要なく使用ができるため、名前の衝突を考慮することなくコードをシンプルに記述できるといったメリットがあります。ラムダ関数は使用すると便利な場面があるため、ラムダ関数の使用方法については覚えておくとよいでしょう。

ラムダ関数は関数型言語、関数型プログラミングという領域に非常に関連があり、私も勉強中です。なかなか奥深いものだと思いますので興味がある方は調べてみていただけると面白いかと思います。