関数の基本

これまでのコードは 1 行ずつ実行されてきました。しかし、同じ機能を再利用する必要がある場合はどうすればよいでしょうか?毎回コピー&ペーストしますか?関数がこの問題を解決します——コードのブロックをパッケージ化し、名前を付けて、必要なときにいつでも呼び出します。これは「コードを書く」から「コードを整理する」への第一歩です。


1. 関数とは

関数は名前付きのコードブロックで、いつでも呼び出すことができます。

PYTHON
# 関数を定義
def say_hello():
    print("Hello!")
    print("Welcome to Python!")

# 関数を呼び出し
say_hello()
say_hello()      # 複数回呼び出せる

出力:

TEXT
Hello!
Welcome to Python!
Hello!
Welcome to Python!
💡 なぜ関数を使うのか? 1)コードの繰り返しを避ける(DRY = Don't Repeat Yourself)。2)コードが理解しやすくなる——良い関数名は大きなコメントよりも有用。3)1 箇所を変更するだけで、すべての呼び出しが自動的に更新される。


2. パラメータ:関数にデータを渡す

関数はパラメータを受け取ることで、より柔軟になります:

PYTHON
def greet(name):
    """名前で挨拶する"""
    print(f"Hello, {name}! Welcome to Python.")

greet("Zhang San")     # Hello, Zhang San! Welcome to Python.
greet("Li Si")         # Hello, Li Si! Welcome to Python.

複数パラメータ

PYTHON
def introduce(name, age, city):
    print(f"My name is {name}, I'm {age} years old, from {city}.")

introduce("Zhang San", 25, "Beijing")
introduce("Li Si", 30, "Shanghai")

パラメータの順序:位置引数

関数を呼び出すとき、引数は位置で一致します:

PYTHON
def create_user(name, age, is_admin):
    print(f"Creating user: {name}, Age: {age}, Admin: {is_admin}")

create_user("Zhang San", 25, False)    # 順序で一致
create_user(False, "Zhang San", 25)    # 順序が間違っている!

例:電卓関数(難易度 ⭐)

PYTHON
def add(a, b):
    print(f"{a} + {b} = {a + b}")

def multiply(a, b):
    print(f"{a} * {b} = {a * b}")

add(5, 3)          # 5 + 3 = 8
multiply(5, 3)     # 5 * 3 = 15
▶ 試してみよう

3. 戻り値

関数は return を使って結果を呼び出し元に返せます:

PYTHON
def add(a, b):
    return a + b

result = add(5, 3)
print(result)               # 8

# 戻り値は式の中で直接使える
total = add(10, 20) + add(30, 40)
print(total)                # 100
⚠️ 注意:関数に return がない場合None を返します。これは「戻り値がない」という意味ではなく、None を返すということです。

複数の戻り値

Python は一度に複数の値を返せます(本質的にタプルを返します):

PYTHON
def get_min_max(numbers):
    return min(numbers), max(numbers)

result = get_min_max([3, 1, 4, 1, 5])
print(result)               # (1, 5)

# 結果を直接アンパック
low, high = get_min_max([3, 1, 4, 1, 5])
print(f"Min: {low}, Max: {high}")

return の動作

return関数の実行を即座に終了し、それ以降のコードは実行されません:

PYTHON
def check_age(age):
    if age < 0:
        return "Age cannot be negative!"    # 早期 return
    if age < 18:
        return "Minor"
    return "Adult"

print(check_age(-5))     # Age cannot be negative!
print(check_age(15))     # Minor
print(check_age(25))     # Adult

例:温度変換ツール(難易度 ⭐⭐)

PYTHON
def celsius_to_fahrenheit(c):
    """Convert Celsius to Fahrenheit"""
    return c * 9 / 5 + 32

def fahrenheit_to_celsius(f):
    """Convert Fahrenheit to Celsius"""
    return (f - 32) * 5 / 9

# テスト
print(f"0°C = {celsius_to_fahrenheit(0):.1f}°F")      # 32.0°F
print(f"100°C = {celsius_to_fahrenheit(100):.1f}°F")   # 212.0°F
print(f"32°F = {fahrenheit_to_celsius(32):.1f}°C")     # 0.0°C
print(f"212°F = {fahrenheit_to_celsius(212):.1f}°C")   # 100.0°C
▶ 試してみよう

4. Docstring

関数定義の最初の行にある """ で書かれたコメントはdocstringと呼ばれ、関数の説明を書きます:

PYTHON
def calculate_bmi(weight, height):
    """
    Calculate Body Mass Index (BMI)

    Parameters:
        weight (float): Body weight in kg
        height (float): Body height in m

    Returns:
        float: BMI value
    """
    return weight / (height ** 2)

# docstring を表示
print(calculate_bmi.__doc__)
help(calculate_bmi)
💡 良い習慣: 関数を作成したら、たとえ 1 行でも docstring を書きましょう。docstring がないと:1)help(your_function) が何も表示しない。2)2 ヶ月後には自分でも関数が何をするか忘れます。フォーマットは強制されませんが、パラメータの説明戻り値の説明を含めることをお勧めします。


5. 関数呼び出しスタック

関数が別の関数を呼び出すとき、Python はメモリ内に「呼び出しスタック」を維持します:

PYTHON
def a():
    print("Entering a")
    b()
    print("Exiting a")

def b():
    print("Entering b")
    c()
    print("Exiting b")

def c():
    print("Entering c")
    print("Exiting c")

a()

出力:

TEXT
Entering a
Entering b
Entering c
Exiting c
Exiting b
Exiting a

皿を積み重ねるように——最後に置かれたものが最初に取られます。この「後入れ先出し」構造をスタックと呼びます。深くネストした関数呼び出しは「スタックオーバーフロー」を引き起こす可能性があります(例:終了条件なしの再帰)。


よくあるユースケース


❓ よくある質問

Q returnprint() の違いは何ですか?
A return は結果を呼び出し元に送り返します。print() はコンソールに出力を表示するだけです。関数が値を外部に渡すには return が必要です。print() では見えるだけで、利用することはできません。
Q 関数に複数の return 文を持たせられますか?
A はい。関数は複数の return 文を持てますが、最初に実行されたものだけが動作し——関数を即座に終了します。これは条件ロジックで一般的です:異なる条件が異なる値を返します。
Q 関数にパラメータは必須ですか?
A いいえ。パラメータのない関数も完全に有効です。例えば、def get_current_time(): はパラメータを必要とせず、現在時刻を直接返します(datetime モジュールを使用)。パラメータの数は、関数が外部データを必要とするかどうかに依存します。

📖 まとめ


📝 練習問題

  1. 初級(難易度 ⭐):関数 is_even(n) を書いてください。整数を受け取り、偶数の場合は True、奇数の場合は False を返します。% 演算子を使用してください。

  2. 中級(難易度 ⭐⭐):関数 grade(score) を書いてください。スコア(0~100)を受け取り、対応する英字グレードを返します:90+ は「A」、80-89 は「B」、70-79 は「C」、60-69 は「D」、60 未満は「F」。if-elif で実装してください。

  3. 上級(難易度 ⭐⭐⭐):3 つの関数 add()subtract()multiply() を書いてください。次に 4 つ目の関数 calculate(a, b, operator) を書いてください。2 つの数値と演算子文字列("+"、"-"、"*")を受け取り、対応する関数を呼び出して結果を返します。サポートされていない演算子の場合は None を返します。

100%