2. lambda式の実践的な使い方

def を用いた関数の場合は直接引数として他の関数に渡すことはできず、どこか別の場所で定義してから渡す必要があるのに対し、 lambda 式はあくまで「式」なので、関数の引数として直接渡すことができる。

ちなみに、lambda式では、先ほどの

f=(lambda a,b: a*a + b*b)(1,2)

という代入式により名前を得ることができ、名前を持った関数 f も変数として扱うことができるが、無名のまま直接関数に渡される場合が多い。

わかりにくいので、例を紹介する。

2.1. lambda式でfor文処理を実装する方法

例えば、様々な商品の価格を抜き出したリストがあり、そのリスト対して、消費税を上乗せした価格情報を取得する処理を実装するとする。

その場合、商品価格のリストをfor文を使用して以下のように実装することができる。

price.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# -*- coding: utf-8 -*-
"""
Created on Tue May 29 16:11:39 2018

@author: user
"""

prices = [3000,2500,10500,4300] #リストpricesの定義

paymentList = []
for i in prices:
    paymentList.append(i * 1.08) #リストpricesの要素に対し1.08を掛けてリストpaymentlistに加える
 
print(paymentList)

実行結果

[3240.0, 2700.0, 11340.0, 4644.0]

同じ処理内容を今度はlambda式を利用して実装する。

その際に、合わせて利用する関数が map() 関数である。

map(function, iterable)

pythonの組み込み関数で、 function の処理を与えて iterable の全ての要素に適用するイテレータを返します。

Function:処理内容
Iterable:処理対象のリスト、ディレクショナリなどの iterable .
pricelamb.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# -*- coding: utf-8 -*-
"""
Created on Tue May 29 16:12:39 2018

@author: user
"""

prices = [3000,2500,10500,4300] #リストpricesの定義

paymentList =map(lambda i : i*1.08 , prices) #リストpricesに対しlambda式の動作を実行
                                             #その結果をpaymentlistに加える
 
print(paymentList)

実行結果

[3240.0, 2700.0, 11340.0, 4644.0]

このようにlambda式とmap関数を併用することで、for文の処理を実装することが可能である。

ちなみにdefを用いて記述すると、

pricedef.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# -*- coding: utf-8 -*-
"""
Created on Tue May 29 16:39:37 2018

@author: user
"""

prices = [3000,2500,10500,4300] #リストpricesの定義

def payment(i): #関数paymentの定義
    return i+(i*1.08) 
   
paymentList =map(payment, prices) #リストpricesの要素に対し、関数paymentの操作を実行
                                  #その結果をpaymentlistに加える
 
print(paymentList)

実行結果

[3240.0, 2700.0, 11340.0, 4644.0]

となる。

2.2. lambda式でif文処理を実装する方法

次にfor文でリストの要素を一つ一つ処理する際に、if文の条件が入るケースについてもlambda式を活用できる。

同じく例として様々な商品の価格を抜き出したリストがあり、そのリストからある金額以上のものを抜き出し、価格の安い順に並べた情報を取得するプログラムを実装する。

今回はlambda式と合わせて filter() 関数を使用する。

filter(function, iterable)

pythonの組み込み関数で iterable の要素のうち function の処理をほどこし真を返す要素でイタレータを構築する(抽出する)。

Function:関数処理
Iterable:処理対象のリスト、ディレクショナリなどの iterable
if.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# -*- coding: utf-8 -*-
"""
Created on Tue May 29 16:34:45 2018

@author: user
"""

prices = [3000,2500,10500,4300]

paymentList = []
for i in prices:
    if i > 3500:
        paymentList.append(i) #pricesの各要素で、3500以上のみをpaymentlistに加える
 
paymentList.sort()
 
print(paymentList)

実行結果

[4300, 10500]

これをlambda式を用いて書くと以下のようになる。

iflamb.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# -*- coding: utf-8 -*-
"""
Created on Tue May 29 16:35:43 2018

@author: user
"""

prices = [3000,2500,10500,4300] #リストpricesの定義

priceList = filter(lambda i : i > 3500, prices)
#リストpricesの要素に対してlambda式の処理を行い、Trueのものだけをpaymentlistに加える

priceList.sort() #paymentlistの中身をソートする
 
print(priceList)

実行結果

[4300, 10500]

また、defを用いて記述すると以下のようになる。

ifdef.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# -*- coding: utf-8 -*-
"""
Created on Tue May 29 16:46:22 2018

@author: user
"""

def checkPrice(price): #関数checkPriceの定義
    return price > 3500
 
prices = [3000,2500,10500,4300] #リストpricesの定義

priceList =filter(checkPrice, prices) #リストpricesに対して関数chevkPriceを実行する
priceList.sort()
 
print(priceList)

実行結果

[4300, 10500]

2.3. lambda式でif文処理を実装する方法2

先ほどはリストについてif文の処理を実施した。同じようにディレクショナリでもif文処理を実行することができる。 同じく例として様々な商品の価格を抜き出したリストがあり、そのリストからある金額以上のものを抜き出すプログラムを実装する。

pricedic.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# -*- coding: utf-8 -*-
"""
Created on Mon Jun  4 14:53:36 2018

@author: user
"""

prices={

    'a':3000,
    'b':2500,
    'c':10500,
    'd':4300,}

print prices.items()
#a,b,c,dという名前の商品と価格のディレクショナリを作成

priceList = filter(lambda (i,j) : j > 3500, prices.items())
#ディレクショナリpricesからkeyとvaluesを取り出し、valuesについてfilter動作を行う

print priceList

実行結果

[('a', 3000), ('c', 10500), ('b', 2500), ('d', 4300)]
[('c', 10500), ('d', 4300)]

2.4. sorted関数のkeyパラメータとの使われ方

sorted(iterable, *, key=None, reverse=False)

組み込み関数で、iterable の要素を並べ替え新たなリストを返す。

Key:比較を行う前にリストの各要素に対して呼び出される関数を指定するパラメータである。
Iterable:処理対象のリスト、ディレクショナリなどの iterable

並べ替えは、関数の実行結果を使って行われる。

sort.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# -*- coding: utf-8 -*-
"""
Created on Thu May 31 11:08:50 2018

@author: user
"""

a = [[0,10,5], [1,9,6], [2,8,7]]
b = sorted(a) #keyを指定しない時は各要素リストのうち一番目の要素の値でソート
print(b)

b = sorted(a, key=lambda x: x[1]) #各要素リストのうち、二番目の要素の値でソート
print(b)

実行結果

[[0, 10, 5], [1, 9, 6], [2, 8, 7]]
[[2, 8, 7], [1, 9, 6], [0, 10, 5]]

上の map() 関数、 filter() 関数、 sorted() 関数と合わせて活用した lambda 式は、特に無名関数と呼ばれる使い方となる。

名前がある関数(今回で言うとpayment,checkPrice)を使用した処理とは対照的に、 lambda 式では関数名を定義せずに使用することができることから無名関数と呼ばれている。

先ほども述べたが、最も重要な違いは、 lambda 式はあくまで”式”であり、”文”ではないことである。つまり、 lambda 式は単一行の式しか持つことができず、複数行のブロックを持つことはできない。このため、 lambda 式で複雑な処理を行うことは困難である。

lambda 式は、関数で書くと冗長になりがちなちょっとした処理をインラインで書くために使われることが多い。

もしある関数を定義して、その関数を再利用する場合は名前をつけて関数定義する必要があるが、この場限りの使い捨ての関数ということであれば、 lambda 式を使うことで簡潔に記述することができる。

2.4.1. 参考サイト

【Python入門】lambda(ラムダ式)の使い方 https://www.sejuku.net/blog/23677

Pythonの無名関数(ラムダ式、lambda)の使い方 https://note.nkmk.me/python-lambda-usage/