Python環境を起動中... 初回のみ数秒かかります
Lesson 11 / 20

関数の応用

このレッスンで学ぶこと

  • *args で可変長の位置引数を受け取れる
  • **kwargs で可変長のキーワード引数を受け取れる
  • lambda 式で1行の無名関数を書ける
  • map()/filter() でリストを効率よく変換・絞り込みできる

1. *args — 可変長の位置引数

*args を使うと、関数が受け取る引数の数を固定しなくて済みます。 渡した引数は タプル として受け取れます。 「何個のデータを渡しても計算できる」汎用関数を作るときに便利です。

💡 重要なのは *(アスタリスク)であって、args という文字ではありません:
*argsargs は単なる変数名です。*values*scores*data など、どんな名前でも同じように動きます。

def calc_mean(*values):   # *values でも OK
def calc_mean(*args):     # *args でも OK
def calc_mean(*numbers):  # *numbers でも OK → すべて同じ動作

慣習として可変長の位置引数には *args可変長のキーワード引数には **kwargs という名前がよく使われます。 下のコードでは *values*args*scores が混在していますが、すべて同じ仕組みです。

sample_1.py
Ctrl+Enter
出力

💡 *values と普通のリスト引数 values の違い:
リストを渡せば結果は同じになりますが、呼び出し側の書き方が変わります。

定義呼び出し方渡し方の制約
def f(*values): f(98, 97, 95) 値をカンマ区切りで並べるだけでOK
def f(values): f([98, 97, 95]) 呼び出し側が必ずリストを用意する必要がある
# *args を使うと、呼び出し元でリストを作らなくて済む
calc_mean(98, 97, 95)          # ✅ そのまま渡せる

# リスト引数の場合は [] が必須
calc_mean_list([98, 97, 95])   # ✅ [] が必要
calc_mean_list(98, 97, 95)     # ❌ TypeError

# 手元にリストがある場合は * で展開して渡せる
data = [98, 97, 95]
calc_mean(*data)               # ✅ * で展開すると *args 関数にも渡せる

使い分けの目安:「バラバラの値を直接渡す」なら *args、 「すでにリストが手元にある」なら通常の引数でもOK。 PyTorchやライブラリのAPIでは *args スタイルが多く使われます。

2. **kwargs — 可変長のキーワード引数

**kwargs を使うと、名前=値 形式の引数を何個でも受け取れます。 受け取った引数は 辞書(dict) として扱えます。 *args が「いくつでも受け取れる位置引数(タプル)」なら、 **kwargs は「いくつでも受け取れるキーワード引数(辞書)」というイメージです。

どんなキーと値が渡されるか実行時まで決まらない柔軟なAPI・設定関数に使います。 機械学習フレームワークのモデル初期化やハイパーパラメータ管理でも このパターンが非常によく登場します。

sample_2.py
Ctrl+Enter
出力

💡 引数の順序ルール: def f(通常引数, *args, **kwargs): の順番で書きます。 **kwargs は必ず最後です。

3. lambda 式 — 1行の無名関数

lambda 引数: 式 で1行の関数を作れます。 名前をつけるほどでもない小さな処理を sorted()map() に渡すときに使います。

sample_3.py
Ctrl+Enter
出力

💡 なぜ sorted() に lambda を渡すのか:
sorted()key パラメータは「各要素から比較に使う値を取り出す関数」を受け取ります。 辞書のリストはそのままでは何を基準に並べるか分からないため、key=... で「どの値を使うか」を関数で教えてあげる必要があります。

# ① 比較関数を def で書く場合(毎回名前をつけるのが手間)
def get_age(p):
    return p["age"]
sorted(patients, key=get_age)     # 関数を渡している

# ② lambda で同じことを1行で(名前不要・書き捨て)
sorted(patients, key=lambda p: p["age"])
# 意味: "患者辞書 p を受け取ったら p['age'] を返す" という
#       1行の関数をその場で作って sorted() に渡している

# ③ reverse=True を加えると降順
sorted(patients, key=lambda p: p["age"], reverse=True)

「1回しか使わない小さな処理」をその場で書き捨てるのが lambda の使いどころです。
処理が複雑な場合は素直に def で名前のある関数を書く方が読みやすくなります。

4. map() と filter()

map(関数, リスト) はリストの全要素に関数を適用します。 filter(関数, リスト) は条件が True の要素だけを抽出します。 どちらも list() で囲んでリストに変換して使います。

sample_4.py
Ctrl+Enter
出力

💡 内包表記 vs map/filter: Python では [f(x) for x in lst] のような内包表記(次のレッスンで学習)がよく使われます。 map/filter と内包表記はどちらでも書けますが、 Pythonコミュニティでは内包表記の方が読みやすいとされています。 ただし map は大きなデータで遅延評価されるためメモリ効率が高い場面もあります。

5. 練習問題

問題 1

可変長引数で検査値の統計を返す関数

*args を使って任意個の血糖値を受け取り、最大・最小・平均をタプルで返す関数 glucose_stats() を作ってください。

exercise_1.py
出力
ヒントを見る(答え+解説)
def glucose_stats(*values):
    return max(values), min(values), sum(values)/len(values)

high, low, avg = glucose_stats(110, 98, 125, 88, 142, 103)
print(f"最大: {high}, 最小: {low}, 平均: {avg:.1f}")
# → 最大: 142, 最小: 88, 平均: 104.3

*values は任意個の引数をタプルとしてまとめて受け取ります。return a, b, c で複数の値を返せるので、統計量をまとめて返す関数によく使われます。

問題 2

lambda で患者リストを年齢降順にソートする

下の患者リストを lambda を使って年齢の降順にソートし、結果を表示してください。

exercise_2.py
出力
ヒントを見る(答え+解説)
patients = [
    {"name": "田中", "age": 58},
    {"name": "鈴木", "age": 34},
    {"name": "佐藤", "age": 71},
    {"name": "高橋", "age": 45},
]

sorted_patients = sorted(patients, key=lambda p: p["age"], reverse=True)

for p in sorted_patients:
    print(f"{p['name']}({p['age']}歳)")
# → 佐藤(71歳)/ 田中(58歳)/ 高橋(45歳)/ 鈴木(34歳)

sorted(key=lambda p: p["age"]) は「辞書の age キーの値で並び替え」を意味します。reverse=True で降順になり、患者を年齢順に並べる場面でよく使うパターンです。

問題 3

filter で異常値を除外する

filter() を使って、下の心拍数リストから 40〜180 の正常範囲に入る値だけを抽出してください。

exercise_3.py
出力
ヒントを見る(答え+解説)
heart_rates = [72, 185, 88, 35, 65, 210, 91, 78, 180, 15]

valid = list(filter(lambda hr: 40 <= hr <= 180, heart_rates))
print("正常範囲の心拍数:", valid)
# → 正常範囲の心拍数: [72, 88, 65, 91, 78, 180]

filter(条件関数, リスト) は条件を満たす要素だけを取り出します。lambda hr: 40 <= hr <= 180 のように Python の連鎖比較を使うと、範囲チェックを1行で書けます。

まとめ

このレッスンのポイント

  • *args で任意個の位置引数をタプルとして受け取れる
  • **kwargs で任意個のキーワード引数を辞書として受け取れる(PyTorchで多用)
  • lambda x: 式 で1行の無名関数。sorted(key=...) でよく使う
  • map(f, lst) で全要素変換、filter(f, lst) で条件抽出
  • Python では内包表記も同等の処理ができる(次レッスンで学習)

自由に試してみましょう:

free_practice.py
Ctrl+Enter
出力

完了するとトップページに進捗が表示されます