【Python】lambda式(無名関数)をわかりやすく解説!

Pythonのlambda式を徹底解説

こんにちは、Youtaです。

今回のテーマはPythonの文法lambda式です。

すずか
すずか

Pythonでlambdaとか出てきたんだけど。

なんて読むのこれ?

先生
先生

lambdaは「ラムダ」と読みます

一種の関数ですよ。

Pythonを学ぶ中で、「lambda式」というワードを見たことはありませんか?

lambda式は、通常defで書く関数を簡潔に記述できる便利な機能なのです。

初心者は少し難しく感じるかもしれませんが、ご安心ください。

この記事では、lambda式の基本から実践的な使い方まで、わかりやすく解説します。

lambda式をサクッと理解して、Python中級者の仲間入りを果たしましょう。

lambda式とは?

lambda式は、Pythonにおける匿名関数の一種です。

匿名、つまり名前を持たない小さな関数を作れます。

lambda式の基本構文です。

lambda 引数: 式

例えば、引数の数値を\(2\)乗するlambda式は次のように書けます。

square = lambda x: x ** 2

result = square(3)  # 結果は9 (=3×3)

squareという変数にlambda式を代入しています。

xが引数で、x ** 2が返される式です。

ちなみに、defを使う普通の関数で同じ処理を書くとこうなります。

def square(x):
    return x ** 2

result = square(3)  # 結果は9 (=3×3)

また、lambda式の引数は\(2\)つ以上でも問題ありません。

xyを引数として、x + yを返す例です。

add = lambda x, y: x + y

result = add(1, 2)  # 結果は3 (=1+2)

普通の関数だとこうなります。

def square(x, y):
    return x + y

result = add(1, 2)  # 結果は3 (=1+2)

引数なしのlambda式も作れます。

現在時刻を表示する例です。

import datetime

get_current_time = lambda: datetime.datetime.now().strftime("%H:%M:%S")

print(get_current_time())
# 14:30:25

普通の関数だとこうなります。

import datetime

def get_current_time():
    return datetime.datetime.now().strftime("%H:%M:%S")

print(get_current_time())
# 14:30:25

このように、lambda式は一種の関数です。

ゆえに、任意のlambda式はdefによる関数に書き換えられます。

lambda式のメリット

では、普通の関数ではなく敢えてlambda式を使う理由は何でしょうか?

結論、次の\(2\)点がlambda式のメリットです。

コードをより簡潔化

lambda式を使うと、コードをスッキリさせられます。

理由は単純で、lambda式は処理を\(1\)行で書くからです。

lambda式と(defを使う)普通の関数を比較してみましょう。

定価と割引率(%)を元に、割引価格を求める処理を例に挙げます。

まずはお馴染みの通常の関数の例から。

def get_discount_price(price, discount_rate):
    discounted = price * (1 - discount_rate)
    return round(discounted, 2)

original_price = 1000
discount = 0.2
final_price = get_discount_price(original_price, discount)

print(f"割引後の価格: {final_price}円")
# 割引後の価格: 800.0円

次はlambda式で同様の処理を行う例です。

get_discount_price = lambda price, discount_rate: round(price * (1 - discount_rate), 2)

original_price = 1000
discount = 0.2
final_price = get_discount_price(original_price, discount)

print(f"割引後の価格: {final_price}円")
# 割引後の価格: 800.0円

通常の関数は最低でも\(2\)行必要ですが、lambda式は\(1\)行で記述できます。

可読性を失わない範囲でlambda式を使うと、コードがより洗練されるでしょう。

一時的な使用に最適

lambda式は、一度きりの使用や短期的な処理に特に適しています。 

lambda式と(defを使う)普通の関数を比較してみましょう。

画面作りでよく使うPythonのtkinterを例に挙げます。

まずは通常の関数の例から。

command引数に関数を渡すと、ボタンを押したときに関数が実行されます。

import tkinter as tk

def button_click():
    print("クリックされました!")

button = tk.Button(
    text="クリック!",
    command=button_click,
)
button.pack()

button.mainloop()

次はlambda式で同様の処理を行う例です。

import tkinter as tk

button = tk.Button(
    text="クリック!",
    command=lambda: print("クリックされました!"),
)
button.pack()

button.mainloop()

どちらのコードも、実行するとボタン付きの画面が出現します。

ボタンを押下すると、「クリックされました!」が出力されます。

「クリック」と表示されたボタン

このように、わざわざdefを使うまでもない処理の場合、lambda式は便利です。

私はテスト的にコードを実行するときに、よくlambda式を使っています。

lambda式のデメリット

すずか
すずか

lambda式があれば、もう普通の関数いらなくね。

先生
先生

そうとも言い切れないんですよ。

lambda式は便利ですが、いくつかの制限があります。

複数の処理を行えない

lambda式では、複数の処理を行えません。

例えば、通常の関数で次のような処理を書いたとしましょう。

def increment(x):
    print('関数に入りました。')

    return x + 1

print文による出力と、②計算結果の返却という\(2\)つの処理を行います。

とても簡単な例ですが、なんとlambda式での書き換えができないのです。

つまり、lambda式による次のコードはエラーとなります。

# increment = lambda x: print('start'), x + 1
# NameError: name 'x' is not defined
先生
先生

一応、lambda式で複数の処理を行う方法はあります。

しかし、初心者向けではないので割愛します。

基本的に、lambda式では単一の処理を行うようにしましょう。

複雑なロジックには不向き

lambda式内で複雑な処理を行うと、可読性の低下に繋がります。

ifelifelseを使って、成績処理の条件分岐を行う場合を考えましょう。

まずは通常の関数です。

def grade(score):
    if score >= 90:
        return 'A'
    elif score >= 80:
        return 'B'
    elif score >= 70:
        return 'C'
    elif score >= 60:
        return 'D'
    else:
        return 'F'

同じ処理をlambda式で書くと、次のようになります。

grade = lambda score: 'A' if score >= 90 else 'B' if score >= 80 else 'C' if score >= 70 else 'D' if score >= 60 else 'F'

どちらが読みやすいかは一目瞭然ですね。

lambda式はシンプルな処理の場合に使いましょう。

変数への代入・変更ができない

lambda式では変数への代入ができません。

例えば、通常の関数とlambda式での変数の扱いの違いを見てみましょう。

# 通常の関数では変数の代入や変更が可能
def normal_function(x):
    y = x + 1  # 新しい変数に代入
    x += 1     # 引数の値を変更

    return x + y

# 変数の代入
# lambda_function = lambda x: y = x + 1
# SyntaxError: cannot assign to lambda

# 変数の更新
# lambda_function = lambda x: x += 1
# SyntaxError: invalid syntax
すずか
すずか

代入できないって関数として致命的じゃね。

先生
先生

確かに不便に思うかもしれません。

ですが、そもそもlambda式は単一の式で表現可能な簡単な処理に使います。

この制限により、lambda式は以下のような場面で使用が難しくなります。

・引数の値を変更する場合
・関数内で定義した変数を使って処理をする場合

複雑な処理や状態の変更が必要な場合は、通常の関数を使うのをお勧めします。

lambda式の実践的な使用例

lambda式の基本を押さえた上で、より実践的な例をご紹介します。

次のような工夫すると、より汎用性の高いlambda式を作れます。

lambda式 × 条件文

if文の三項演算子を活用して、lambda式で条件分岐をさせられます。

三項演算子はPythonの構文で、if文を1行で書く手法です。

構文は以下の通りです。

<条件が真の場合の値> if <条件> else <条件が偽の場合の値>

具体例を見てみましょう。

x = 10

result = "大きい" if x > 5 else "小さい"

print(result)
# 大きい

xが\(5\)より大きい場合に「大きい」を、そうでない場合に「小さい」と表示します。

これは、下記の記述と実質的に同じです。

x = 10

if x > 5:
    result = "大きい"
else:
    result = "小さい"

print(result)
# 大きい

\(6\)文字以上で文字列を大文字にするlambda式です。

capitalize_long_strings = lambda s: s.upper() if len(s) >= 6 else s

print(capitalize_long_strings("hello"))   # 出力: hello
print(capitalize_long_strings("goodbye")) # 出力: GOODBYE

def文による普通の関数だとこうなります。

# 三項演算子を使う場合
def capitalize_long_strings(s):
    return s.upper() if len(s) >= 6 else s

# 三項演算子を使わない場合
def capitalize_long_strings(s):
    if len(s) >= 6:
        return s.upper()
    else:
        return s

print(capitalize_long_strings("hello"))
# hello

print(capitalize_long_strings("goodbye"))
# GOODBYE

lambda式 × 複数の戻り値

lambda式は直接複数の値を返すことはできません。

しかし、タプル・リスト・辞書を使うとlambda式でも複数の値をまとめて返せます。

タプルを利用して、\(2\)数の和・差・積・商を一気に返す例です。

multiple_return = lambda x, y: (x + y, x - y, x * y, x / y if y != 0 else "除算エラー")

result = multiple_return(10, 5)
print(result)
# (15, 5, 50, 2.0)

sum_result, diff_result, prod_result, div_result = result
print(f"和: {sum_result}, 差: {diff_result}, 積: {prod_result}, 商: {div_result}")
# 和: 15, 差: 5, 積: 50, 商: 2.0

次は、リストを使って各種統計値をまとめて返す例です。

stats = lambda numbers: [sum(numbers), sum(numbers)/len(numbers), max(numbers), min(numbers)]

data = [1, 2, 3, 4, 5]
result = stats(data)
print(result)  # 出力: [15, 3.0, 5, 1]

total, average, maximum, minimum = result
print(f"合計: {total}, 平均: {average}, 最大: {maximum}, 最小: {minimum}")x
# 合計: 15, 平均: 3.0, 最大: 5, 最小: 1

lambda式 × デフォルト引数

lambda式にはデフォルト引数を設定できます。

引数が省略された場合に、デフォルト値を使って処理をしてくれます。

構文は次の通りです。

lambda <引数>=<デフォルト値>: <処理>

先ほどの\(2\)数の足し算をするlamba式を改良しました。

引数が一つだと、その数に\(1\)を足した数を返します。

add = lambda x, y=1: x + y

print(add(5))
# 6 (yのデフォルト値1を使用)

print(add(5, 2))
# 7

lambda式 × 可変長引数

lambda式には可変長引数を設定できます。

これにより、好きな数だけ引数を受け取れるようにできます。

構文は次の通りです。

lambda *args: <処理>

受け取った複数の文字列を「,」でつなぐlambda式の例です。

join_strings = lambda *args: ', '.join(args)

print(join_strings('apple', 'banana', 'cherry'))
# apple, banana, cherry

print(join_strings('red', 'green', 'blue', 'yellow'))
# red, green, blue, yellow

lambda式 × キーワード引数

lambda式にはキーワード引数を設定できます。

これにより、名前付きの引数を好きな数だけ受け取ることができます。

構文は次の通りです。

lambda **kwargs: <処理>

例えば、簡単な自己紹介文を作成する関数を作ってみましょう。

人物の情報をキーワード引数として受け取ります。

introduce = lambda **kwargs: f"私の名前は{kwargs.get('name', '名無し')}です。年齢は{kwargs.get('age', '秘密')}歳です。"

print(introduce(name="山田太郎", age=30))
# 私の名前は山田太郎です。年齢は30歳です。

print(introduce(name="佐藤花子"))
# 私の名前は佐藤花子です。年齢は秘密歳です。

kwargs.get()で、引数が省かれた場合のデフォルト値を設定しているのもポイントです。

lambda式の練習問題

lambda式を理解できたか確認しましょう。

簡単な問題を\(5\)問用意しましたので、ぜひ挑戦してみてください!

問題\(1\): 次のlambda式は何を行いますか。

multiply = lambda x, y: x * y

2つの引数を掛け合わせます。

問題\(2\): 以下のコードの出力は何になりますか。

greet = lambda name: f"Hello, {name}!"

print(greet("Python"))

出力は "Hello, Python!" です。

問題\(3\): 以下のコードの出力は何になりますか。

(lambda x: x + 5)(10)

出力は\(15\)です。\(10\)に\(5\)を足しています。

問題\(4\): lambda式で、与えられた数値を2で割った余りを返す関数を作りましょう。

先生
先生

%で余りを計算できますね。

関数名remainderや引数名xは自由です。

remainder = lambda x: x % 2

問題\(5\): lambda式で、文字列の最初の文字を大文字にする関数を作りましょう。

すずか
すずか

確か、文字列"Python"の\(0\)番目ってPだよね。

先生
先生

そうですね。

また"Python"[3:]で\(3\)番目以降の文字列"hon"が取れます。

すずか
すずか

文字を大文字にする方法は、さっき見たような…。

関数名capitalize_firstや引数名sは自由です。

capitalize_first = lambda s: s[0].upper() + s[1:]

まとめ

lambda式は、Pythonにおいて非常に便利なツールです。

簡潔で読みやすいコードを書くのに役立ち、特に一時的な関数が必要な場合に重宝します。

最後にもう一度、lambda式の構文を確認します。

lambda 引数: 式

使用にあたっては、メリット・デメリットも把握しておきましょう。

余力のある方は、実践的なテクニックもマスターすればGOODです。

この記事が皆様のお役に立てたら幸いです。

ご覧いただきありがとうございました。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA