閉じる

Pythonのreturnと戻り値とは?意味・書き方・使い方を図解で解説

Pythonで関数を書くとき、必ず出てくるのがreturnと戻り値です。

しかし「とりあえず書いているけれど、実はよく分かっていない」という方も少なくありません。

この記事では、returnの意味・役割から戻り値の型、実務での使い方までを、図解とサンプルコードを交えながら丁寧に解説します。

returnとは何か

returnの基本的な意味と役割

Pythonにおけるreturnは、関数の処理結果(戻り値)を呼び出し元に返すための命令です。

より正確に言うと、次の2つの動きを同時に行います。

  1. 戻り値を呼び出し元に渡す
  2. その時点で関数の実行を終了する

つまり、関数の中でreturnが実行されると、それ以降の行は一切実行されません。

これが、処理の終了条件を明確にしたり、早期終了(early return)を実現したりするために重要なポイントです。

式の評価とreturnの動き

returnは、「値」だけでなく式全体を受け取ります。

Pythonは次の順番で動作します。

  1. returnの右側に書かれた式を評価して、1つの値を求める
  2. 評価結果の値を、関数の戻り値として呼び出し元に返す
  3. 関数の実行を終了する

例えば次のコードを見てください。

Python
def calc():
    # ここで「1 + 2 * 3」という式が評価される
    return 1 + 2 * 3

result = calc()
print(result)
実行結果
7

この場合、1 + 2 * 3が先に計算され、7という値になってから、呼び出し元に返されています。

returnは「計算式そのもの」ではなく、「計算した結果の値」を返すという点が重要です。

関数終了とreturnの関係

returnが実行された瞬間、その関数はそこで終了します

そのため、returnの後ろに書いた処理は、一切実行されません。

Python
def sample():
    print("処理A")
    return "終了"
    print("処理B")  # ここには到達しない

value = sample()
print("戻り値:", value)
実行結果
処理A
戻り値: 終了

このように、print("処理B")は実行されません。

もしreturnの後に処理を書いてしまった場合、そのコードは「死んだコード(dead code)」になっている可能性が高いので、設計ミスのサインとして見直す必要があります。

戻り値の基本

戻り値とは何か

戻り値とは、関数が計算・処理を行った結果として、呼び出し元に返す値のことです。

関数を「入力を受け取り、出力を返す機械」と考えると、次のように整理できます。

  • 引数: 関数に渡す入力データ
  • 戻り値: 関数から受け取る出力データ

関数定義側ではreturn 値として戻り値を決め、呼び出し側では受け取る変数 = 関数()という形で、戻り値を変数に保存して利用します。

戻り値の型

Pythonでは、戻り値の「型」は特に宣言しませんが、実際には任意の型を返すことができます。

代表的な戻り値の型を表にまとめます。

戻り値の型主な用途
int0, 1, 100数値計算、カウント結果
float1.5, 3.14小数を含む計算結果
str“OK”メッセージや名前などの文字列
boolTrue, False条件判定の結果
list[1, 2, 3]複数要素を順序付きで返す
dict{“x”: 1}名前付きの複数情報を返す
tuple(1, “a”)複数の戻り値をまとめて返す(後述)
NoneNone戻り値が特にないことを表現

例えば、次のようにさまざまな型を返すことができます。

Python
def get_number():
    return 42  # int

def get_message():
    return "Hello"  # str

def is_even(n):
    return n % 2 == 0  # bool(True/False)

num = get_number()
msg = get_message()
flag = is_even(10)

print(num, type(num))
print(msg, type(msg))
print(flag, type(flag))
実行結果
42 <class 'int'>
Hello <class 'str'>
True <class 'bool'>

Pythonの関数は「どんな型でも返せる」柔軟さがあるため、関数設計の自由度が高くなります。

戻り値なし(None)とはどういう意味か

Pythonでは、明示的に何も返さなかった場合でも、実はNoneという値が返されています

次の2つは同じ意味です。

Python
def func_a():
    # returnを書かない
    print("処理だけ実行")

def func_b():
    print("処理だけ実行")
    return  # 値を指定しないreturn

どちらも呼び出すとNoneが返されます。

Python
result_a = func_a()
result_b = func_b()

print("func_aの戻り値:", result_a)
print("func_bの戻り値:", result_b)
実行結果
処理だけ実行
処理だけ実行
func_aの戻り値: None
func_bの戻り値: None

「戻り値なしの関数」=「戻り値がNoneの関数」だと理解すると、動きがはっきりします。

実務では、Noneを「エラー」や「見つからなかった」という特別な状態を表す値として使うこともよくあります。

returnの書き方と使い方

単一の戻り値を返す書き方

最も基本的な形は、1つの値をreturnで返す書き方です。

Python
def add(a, b):
    """2つの数値を足し合わせて結果を返す関数"""
    result = a + b
    return result  # 計算結果を1つだけ返す

sum_value = add(10, 20)
print("結果:", sum_value)
実行結果
結果: 30

このように、return 値で返し、呼び出し側では変数 = 関数名(…)という形で受け取ります。

「関数は1つの値を返す」のが基本形ですが、Pythonでは複数の値を返すこともできます。

複数の戻り値を返す書き方

Pythonでは、カンマ区切りで値を書くことで、複数の戻り値を返すことができます。

内部的にはtuple(タプル)としてまとめて返されます。

Python
def calc_total_and_average(scores):
    """点数リストから合計と平均を計算して返す"""
    total = sum(scores)
    avg = total / len(scores)
    return total, avg  # カンマで区切ると複数の値を返せる

scores = [80, 90, 70]
total, average = calc_total_and_average(scores)  # 2つの変数で受け取る

print("合計:", total)
print("平均:", average)
実行結果
合計: 240
平均: 80.0

もちろん、1つの変数でタプルのまま受け取ることも可能です。

Python
result = calc_total_and_average(scores)
print(result, type(result))
実行結果
(240, 80.0) <class 'tuple'>

「関数から複数の情報を返したいときは、タプル・リスト・辞書にまとめる」という発想が大切です。

条件分岐(if)とreturnの組み合わせ

条件によって戻り値を変えたい場合は、ifreturnを組み合わせます。

Python
def judge_score(score):
    """点数に応じて評価文字列を返す"""
    if score >= 80:
        return "合格"
    else:
        return "不合格"

print(judge_score(90))
print(judge_score(50))
実行結果
合格
不合格

ここで重要なのは、すべてのパスで何らかの値をreturnしているかを意識することです。

どこか1つでもreturnを書き忘れると、そこを通ったときにはNoneが返ってしまいます。

Python
def bad_judge(score):
    if score >= 80:
        return "合格"
    # elseを書き忘れている

result = bad_judge(50)
print(result)  # Noneになってしまう
実行結果
None

このようなバグを防ぐには、if/elif/elseをきちんと書くか、関数の最後にデフォルトのreturnを書くことが大切です。

早期returnで処理をわかりやすくする

早期return(early return)とは、エラーや例外的な状態を最初にチェックし、その場で関数を終了させる書き方です。

これにより、ネストが深くならず、読みやすいコードになります。

Python
def get_first_item(lst):
    """リストの最初の要素を返す。空ならNoneを返す。"""
    if not lst:  # 空リストやNoneなら早期return
        return None

    # ここに来るのは「lstが空でない」場合だけ
    return lst[0]

print(get_first_item([1, 2, 3]))
print(get_first_item([]))   # 空リスト
実行結果
1
None

早期returnを使わないと、次のようにネストが深くなります。

Python
def get_first_item_bad(lst):
    if lst:
        return lst[0]
    else:
        return None

小さな例では差が分かりにくいですが、実務コードでは早期returnを活用することで、処理の流れが平坦になり、バグも入りにくくなります。

ループ(for・while)とreturnの挙動

ループの中でreturnを実行すると、その瞬間にループだけでなく関数全体が終了します。

Python
def find_first_even(numbers):
    """リストから最初に見つかった偶数を返す。なければNone。"""
    for n in numbers:
        if n % 2 == 0:
            return n  # 見つかった時点で関数終了
    # ループを最後まで回っても見つからなかった場合
    return None

print(find_first_even([1, 3, 5, 8, 10]))
print(find_first_even([1, 3, 5]))
実行結果
8
None

この例では、8が見つかった瞬間に関数が終わるため、10は調べられません。

「ループを全部見たいのか」「最初の1件だけで良いのか」を意識して、returnをどこに置くか設計することが重要です。

図解で理解するreturnと戻り値

ステップ実行で見るreturnの流れ

実際に、簡単な関数をステップごとに追ってみます。

Python
def multiply(a, b):
    """2つの数値を掛け合わせて返す"""
    c = a * b      # ステップ2: 計算
    return c       # ステップ3: 戻り値を返して関数終了

x = 3
y = 4
z = multiply(x, y)  # ステップ1: 関数呼び出し
print(z)            # ステップ4: 戻り値が使われる
実行結果
12

流れを整理すると次の通りです。

  1. 呼び出し元でmultiply(x, y)に到達すると、処理は関数の先頭にジャンプします。
  2. 関数内でc = a * bが実行されます。
  3. return cに到達したら、cの値(12)を持って呼び出し元に戻り、関数は終了します。
  4. 呼び出し元では、z = multiply(x, y)が「z = 12」と同じ意味になり、次の行print(z)へ進みます。

このように、関数呼び出しは「一時的に関数に飛んで、戻り値を持って帰ってくる」動きをしていると考えると理解しやすくなります。

return値が呼び出し元に渡る仕組み

実際のPythonの内部では、関数を呼び出すたびにスタックフレームという「作業領域」が積み上がります。

  1. 呼び出し元のフレーム(現在の作業領域)がある
  2. 関数を呼び出すと、新しいフレームが上に積まれ、その中で処理が行われる
  3. return 値が実行されると、その値を呼び出し元に渡し、関数のフレームは破棄される
  4. 呼び出し元のフレームに戻り、戻り値が変数に代入される

このため、関数の中で作ったローカル変数は、関数が終わると消えるという性質があります。

戻り値として返したい情報は、必ずreturnで明示的に外へ出す必要があります。

Python
def create_message(name):
    message = f"こんにちは、{name}さん"  # ローカル変数
    return message  # ここで外へ持ち出す

msg = create_message("太郎")
print(msg)
実行結果
こんにちは、太郎さん

もしreturnしなければ、messageは関数の終了と共に消えてしまい、呼び出し元からは参照できません。

実務コードでのreturnと戻り値の設計例

実務では、関数の戻り値の設計がコード全体の読みやすさ・安全性に大きく影響します。

シンプルな例として、「ユーザーIDからユーザー情報を取得する関数」を考えます。

Python
def get_user(users, user_id):
    """
    ユーザー一覧(dict)から、指定IDのユーザー情報(dict)を返す。
    見つからなければNoneを返す。
    """
    # usersは {"u1": {...}, "u2": {...}} のような辞書を想定
    if user_id in users:
        return users[user_id]  # 正常時: ユーザー情報を返す
    
    # 見つからない場合はNoneで特別な状態を表現
    return None


# ダミーデータ
users_data = {
    "u1": {"name": "田中", "age": 30},
    "u2": {"name": "佐藤", "age": 25},
}

user = get_user(users_data, "u1")

if user is None:
    print("ユーザーが見つかりませんでした")
else:
    print("ユーザー名:", user["name"])
実行結果
ユーザー名: 田中

このパターンでは、次のような設計ポイントがあります。

  • 見つかった場合: ユーザー情報(dict)を返す
  • 見つからない場合: Noneを返して「未取得」を表現
  • 呼び出し元ではNoneチェックを必ず行う

もっと情報量を増やしたい場合は、複数の戻り値を組み合わせる形も考えられます。

Python
def get_user_with_status(users, user_id):
    """
    (found, user) の2つを返す。
    found: bool(見つかったかどうか)
    user: 見つかった場合はユーザー情報、見つからなければNone
    """
    if user_id in users:
        return True, users[user_id]
    return False, None

found, user = get_user_with_status(users_data, "u3")

if not found:
    print("ユーザーが見つかりませんでした")
else:
    print("ユーザー名:", user["name"])
実行結果
ユーザーが見つかりませんでした

このように、戻り値にどんな情報を持たせるかを意識的に設計することで、呼び出し元のコードがシンプルで分かりやすくなります。

まとめ

Pythonのreturnは、「値を返す」と「関数を終了する」という2つの役割を持っています。

戻り値は1つでも複数でもよく、型の制限もありませんが、関数ごとに「どんな状況で何を返すか」を一貫して設計することが重要です。

また、早期returnやNoneの活用により、条件分岐やループを含む処理も分かりやすく整理できます。

この記事で学んだ考え方とサンプルコードをもとに、実際のプロジェクトで「戻り値設計」を意識しながら関数を書く練習をしてみてください。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!