モチベーション
昨日の「学生の成績データを処理する関数(最高得点者:点数、最低得点者:点数、平均点)」をもっと簡潔に記述したい
lambda関数について
#lambda関数を使う
#lambda内の引数が実際に受け取るもの
students = [("Alice", 85), ("Bob", 92), ("Charlie", 78)]
best_student = max(students, key=lambda x: x[1])
# max()関数は、studentsリストの各要素を1つずつlambda関数に渡す
# つまり:
# 1回目: lambda関数は ("Alice", 85) を受け取る
# 2回目: lambda関数は ("Bob", 92) を受け取る
# 3回目: lambda関数は ("Charlie", 78) を受け取る
#構造
lambda x: x[1]
#│ │ │
#│ │ └── 戻り値(return する値)
#│ └───── 引数(parameter)
#└──────────── lambda キーワード
#引数
lambda x: # xという名前の引数を1つ受け取る
# ↑
# 引数名(自由に決められる)
# 引数は複数でもOK
lambda x, y: x + y # 2つの引数
lambda a, b, c: a + b + c # 3つの引数
#戻り値
lambda x: x[1]
# ↑
# xの1番目の要素を返す
# 他の例
lambda x: x[0] # xの0番目の要素
lambda x: x * 2 # xを2倍した値
lambda x: len(x) # xの長さ
以下の2つは同じ動作をする
# 通常の関数定義
def get_score(student):
return student[1]
# lambda を使った同じ機能
lambda x: x[1]
key=の有無
# ✅ 正しい:key= を明示
max(students, key=lambda x: x[1])
# 「studentsの各要素に対して、lambda関数を適用した結果で比較してください」
# ❌ 間違い:key= なし
max(students, lambda x: x[1])
# 「studentsとlambda関数を直接比較してください」← 無理!
- key= は省略できない:Pythonの文法で決まっている
- 省略すると:lambda関数が比較対象として扱われてエラー
- 理由:max(a, b, c) と max(list, key=func) は別の使い方
- 正解:max(students, key=lambda x: x[1])
これはPythonの言語仕様による制限で、「こういうものだ」と覚えておく必要がある。
平均点を求める
key= 引数があるのは、比較や並び替えをする関数だけ:
# ❌ これらの関数にはkey引数がない
sum(scores, key=lambda x: x[1]) # TypeError!
len(scores, key=lambda x: x[1]) # TypeError!
map関数をつかう
map() 関数は、リストや配列の各要素に同じ処理を適用して、新しいリストを作る関数
#構造
map(function, iterable)
#│ │ │
#│ │ └── 処理対象のデータ(リスト、タプルなど)
#│ └─────────── 各要素に適用する関数
#└─────────────── map キーワード
numbers = [1, 2, 3, 4, 5]
# map()を使う場合
doubled = map(lambda x: x * 2, numbers)
result = list(doubled)
print(result) # [2, 4, 6, 8, 10]
# 同じことをfor文で書くと
result = []
for num in numbers:
result.append(num * 2)
print(result) # [2, 4, 6, 8, 10]
結果、昨日の記述よりかなり短く出来た...!🙌
scores = [("田中", 85), ("佐藤", 92), ("山田", 78), ("鈴木", 96), ("高橋", 81)]
max_name,max_score=max(scores , key=lambda x:x[1])
min_name,min_score=min(scores , key=lambda x:x[1])
average = sum(map(lambda x:x[1],scores)) / len(scores)
print(f'最高は{max_name} 得点は{max_score}点')
print(f'最低は{min_name} 得点は{min_score}点')
print(f'平均は{average}点')
おまけ
関数内のローカル関数のスコープ
max_name, max_score = max(scores, key=lambda x: x[1])
# ↑
# この x は max() 内でのみ有効
min_name, min_score = min(scores, key=lambda x: x[1])
# ↑
# この x は min() 内でのみ有効
average = sum(map(lambda x: x[1], scores)) / len(scores)
# ↑
# この x は map() 内でのみ有効