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

関数の基礎

このレッスンで学ぶこと

  • def で関数を定義し、return で値を返せる
  • 引数・デフォルト引数・キーワード引数を使い分けられる
  • 複数の値をまとめて返せる
  • スコープ(変数の有効範囲)の基本を理解できる

1. 関数の定義と呼び出し

関数は「処理に名前をつけて再利用できるブロック」です。 同じ処理を何度も書く代わりに関数にまとめると、 コードが読みやすくなり、バグが起きたときの修正箇所も1か所で済みます。

機械学習プロジェクトでは前処理・評価指標・データ変換など、 ほぼすべての処理が関数(またはメソッド)として実装されます。

💡 関数定義の基本構文:

def 関数名(引数1, 引数2, ...):
    """docstring(説明文・省略可)"""
    # 処理
    return 戻り値

  • def(define の略):関数を定義するキーワード
  • 引数:関数に渡す入力値。なくても良い(def hello(): のように空欄にする)
  • return:呼び出し元に値を返す。省略すると None を返す
  • 関数本体はインデント(字下げ)で区別される
sample_1.py
Ctrl+Enter
出力

💡 docstring(関数の説明):
def の直後に """説明""" と書くとドキュメント文字列(docstring)になります。 チームで使う関数には書く習慣をつけましょう。

def calc_bmi(weight, height):
    """BMIを計算して返す。
    引数:
        weight (float): 体重(kg)
        height (float): 身長(m)
    戻り値:
        float: BMI値
    """
    return weight / height ** 2

help(calc_bmi)  # docstring を表示できる(上のセルで定義後に試してみよう)

2. デフォルト引数とキーワード引数

デフォルト引数 は呼び出し時に省略できる引数です。 キーワード引数引数名=値 の形で順序を指定せずに渡せます。 PyTorchの関数呼び出しはキーワード引数だらけなので、今から慣れておきましょう。

💡 デフォルト引数とキーワード引数の違い:

種類 書く場所 意味
デフォルト引数関数の定義省略されたとき使われる値を設定するdef f(x, mode="train"):
キーワード引数関数の呼び出し引数名を指定して渡す。順序を変えてもOKf(x, mode="eval")
def greet(name, greeting="こんにちは"):   # greeting はデフォルト引数
    print(f"{greeting}、{name}さん")

greet("田中")                     # → "こんにちは、田中さん"(デフォルト使用)
greet("鈴木", greeting="おはよう") # → "おはよう、鈴木さん"(キーワード引数で上書き)
greet(greeting="さようなら", name="佐藤") # → 順序を変えてもOK
sample_2.py
Ctrl+Enter
出力

⚠ デフォルト引数の注意点(リスト・辞書を使うのは危険):
デフォルト引数は関数定義時に1回だけ作られるため、 リストや辞書をデフォルトにすると全呼び出しで同じオブジェクトを共有してしまいます。

# NG: デフォルト引数にリストを使う(バグになる)
def add_item(x, result=[]):   # この [] は関数定義時に1回だけ作られる
    result.append(x)
    return result

print(add_item(1))  # → [1]
print(add_item(2))  # → [1, 2]  ← 前回の結果が残っている!
print(add_item(3))  # → [1, 2, 3]

# OK: None をデフォルトにして、関数内で初期化する
def add_item_safe(x, result=None):
    if result is None:
        result = []   # 毎回新しいリストを作成
    result.append(x)
    return result

数値・文字列・タプルなどの変更できない(イミュータブルな)値はデフォルト引数に使っても安全です。

3. 複数の値を返す

Pythonの関数は複数の値をタプルとして返せます(L07で学んだタプルのアンパックを活用)。 評価関数が「精度、再現率、F1スコア」を一度に返すような場面でよく使います。

sample_3.py
Ctrl+Enter
出力

4. スコープ(変数の有効範囲)

関数の中で定義した変数は ローカル変数 と呼ばれ、関数の外からはアクセスできません。 関数の外で定義した変数は グローバル変数 で、関数内から読み取り専用で参照できます。 この「スコープ」の概念はバグの原因になりやすいので、しっかり押さえておきましょう。

sample_4.py
Ctrl+Enter
出力

💡 純粋関数(Pure Function)を意識しよう: 「同じ引数を渡せば常に同じ結果を返す」関数を純粋関数と言います。 副作用(グローバル変数の書き換え、ファイルI/Oなど)がないため、 テストしやすく、バグが出にくいです。 PyTorchの前処理・損失計算など、AI系コードでは純粋関数が基本です。

純粋でない関数の例:

# ❌ 純粋でない関数(グローバル変数に依存)
threshold = 0.5           # 関数の外で定義されたグローバル変数

def is_positive(score):   # threshold を引数で受け取っていない
    return score >= threshold

print(is_positive(0.6))   # → True
threshold = 0.8           # グローバル変数を変更
print(is_positive(0.6))   # → False(同じ引数なのに結果が変わった!)

# ✅ 純粋関数にするなら → 依存する値も引数に渡す
def is_positive_pure(score, threshold=0.5):
    return score >= threshold  # 引数だけに依存 → 常に同じ結果

5. 練習問題

問題 1

BMI計算と分類を1つの関数にまとめる

体重(kg)と身長(m)を受け取り、BMI値と分類をタプルで返す関数 calc_bmi_with_category(weight, height) を作ってください。
分類の閾値:BMI < 18.5 → 低体重 / 18.5 以上 25.0 未満 → 普通体重 / 25.0 以上 30.0 未満 → 肥満(1度)/ 30.0 以上 → 肥満(2度以上)

exercise_1.py
出力
ヒントを見る(答え+解説)
def calc_bmi_with_category(weight, height):
    bmi = weight / height ** 2
    if bmi < 18.5:
        category = "低体重"
    elif bmi < 25.0:
        category = "普通体重"
    elif bmi < 30.0:
        category = "肥満(1度)"
    else:
        category = "肥満(2度以上)"
    return bmi, category

bmi, category = calc_bmi_with_category(72.5, 1.72)
print(f"BMI: {bmi:.2f}, 分類: {category}")
# → BMI: 24.51, 分類: 普通体重

bmi2, cat2 = calc_bmi_with_category(48.0, 1.65)
print(f"BMI: {bmi2:.2f}, 分類: {cat2}")
# → BMI: 17.63, 分類: 低体重

return a, b で複数の値をタプルとして返し、呼び出し側で x, y = 関数() のようにアンパックして受け取ります。BMI計算など「値+判定」を同時に返す場面でよく使うパターンです。

問題 2

正規化関数を作る(デフォルト引数つき)

値のリストを受け取り、Min-Max正規化(0〜1スケール)したリストを返す関数を作ってください。 引数に feature_range=(0, 1) のデフォルト引数を持たせてください。

exercise_2.py
出力
ヒントを見る(答え+解説)
def minmax_normalize(values, feature_range=(0, 1)):
    low, high = feature_range
    min_v = min(values)
    max_v = max(values)
    result = []
    for v in values:
        norm = (v - min_v) / (max_v - min_v)
        scaled = low + norm * (high - low)
        result.append(scaled)
    return result

data = [80, 120, 100, 150, 90, 110]
normalized = minmax_normalize(data)
print("正規化後:", [f"{v:.3f}" for v in normalized])
# → ['0.000', '0.571', '0.286', '1.000', '0.143', '0.429']

デフォルト引数 feature_range=(0, 1) を使うと、引数を省略した場合は 0〜1、指定した場合は任意の範囲で正規化できます。機械学習の前処理で頻出のパターンです。

問題 3

患者サマリー文字列を返す関数を作る

名前・年齢・診断名を受け取り、 "田中 一郎(58歳): 2型糖尿病" 形式の文字列を返す関数を作ってください。 診断名のデフォルト値は "未診断" にしてください。

exercise_3.py
出力
ヒントを見る(答え+解説)
def patient_summary(name, age, diagnosis="未診断"):
    return f"{name}({age}歳): {diagnosis}"

print(patient_summary("田中 一郎", 58, "2型糖尿病"))
print(patient_summary("鈴木 花子", 34))  # 診断なし(デフォルト)
# → 田中 一郎(58歳): 2型糖尿病
# → 鈴木 花子(34歳): 未診断

デフォルト引数 diagnosis="未診断" を設定すると、診断名を省略した呼び出しでも動作します。return で f-string を直接返すのが最もシンプルな書き方です。

まとめ

このレッスンのポイント

  • def 関数名(引数): で関数を定義、return 値 で結果を返す
  • デフォルト引数 def f(x, 引数名=デフォルト値): で省略可能な引数を設定できる(例: threshold=0.5ward="外来"
  • キーワード引数 f(x, 引数名=値) で順序を入れ替えて渡せる(PyTorchで多用)
  • return a, b, c でタプルとして複数の値を返せる
  • ローカル変数は関数内でのみ有効。グローバル変数の書き換えは避けるのが基本
  • 純粋関数(引数のみに依存)はテストしやすくバグが少ない

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

free_practice.py
Ctrl+Enter
出力

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