Python | 関数:引数と返り値

Python
スポンサーリンク

概要(引数は「入力」、返り値は「出力」——関数の往復の道筋)

関数は「処理に名前をつけて再利用」する仕組みです。その入口が引数(関数に渡す値)、出口が返り値(return で返す結果)。引数で必要な材料を受け取り、計算した結果を返り値として外へ渡す——この往復の流れを正しく設計できると、コードが短く、安全で、拡張しやすくなります。

def add(a, b):      # 引数 a, b(入力)
    return a + b    # 返り値(出力)

print(add(3, 5))    # 8
Python

引数の基本(位置・キーワード・デフォルト)

位置引数とキーワード引数

位置引数は「順番」でマッチし、キーワード引数は「名前」でマッチします。読みやすさと柔軟性のため、外部に公開する関数はキーワード引数が有効です。

def power(x, exp):
    return x ** exp

print(power(2, 3))         # 位置引数
print(power(x=2, exp=3))   # キーワード引数
Python

デフォルト引数(省略可能な値)

よくある既定値は「デフォルト」で持たせ、必要なときだけ上書きします。呼び出しを簡潔に保てます。

def power(x, exp=2):
    return x ** exp

print(power(3))            # 9(既定は2乗)
print(power(3, 4))         # 81
Python

引数の順序(位置 → 可変長 → キーワード → キーワード可変長)

正しい並びは「位置引数 → 位置の可変長(args) → キーワード引数 → キーワードの可変長(*kwargs)」。これを守るとシグネチャが明確になり、TypeError を避けられます。

def demo(a, b, *args, c=0, **kwargs):
    pass
Python

引数の拡張(*args, **kwargs・位置限定・キーワード限定)

可変長引数(複数をまとめて受ける)

引数の数が決まっていない時に使います。args は位置引数をタプルに、*kwargs はキーワード引数を辞書にまとめます。

def summarize(*nums, avg=False):
    total = sum(nums)
    return total / len(nums) if avg else total

print(summarize(1, 2, 3))          # 6
print(summarize(1, 2, 3, avg=True))# 2.0
Python

位置限定引数(/)とキーワード限定引数(*)

公開 API を安定させたいときに有効です。/ の左は「位置のみ」、* の右は「キーワードのみ」で受けます。

def scale(x, /, factor, *, rounding=None):
    y = x * factor
    return round(y, rounding) if rounding is not None else y

print(scale(10, 0.3))                    # 3.0(xは位置のみ)
print(scale(10, 0.3, rounding=2))        # 3.0(roundingはキーワードのみ)
# scale(x=10, 0.3)  # TypeError(xは位置のみ)
# scale(10, 0.3, 2) # TypeError(roundingはキーワードのみ)
Python

引数のアンパック(渡す側のテクニック)

渡す側も * と ** で展開できます。既存データをきれいに再利用できます。

def connect(host, port, secure=False):
    return (host, port, secure)

args = ("example.com", 443)
opts = {"secure": True}
print(connect(*args, **opts))  # ('example.com', 443, True)
Python

返り値の基本(return・複数値・None・早期return)

return は「ここで出ていく」

return に達したら即終了し、値を返します。複数の分岐で「早期 return」を使うと読みやすくなります。

def safe_div(a, b):
    if b == 0:
        return None   # 早期に失敗を示す
    return a / b
Python

複数の値を返す(タプルが自然)

Python はカンマ区切りで複数返せます(実体はタプル)。受け取り側ではアンパックで分解。

def stats(nums):
    return sum(nums), len(nums), min(nums), max(nums)

total, count, mn, mx = stats([1, 2, 3])
Python

戻り値がないときは None

return を省略すると None が返ります。呼び出し側で「使う値があるのか」を意識して設計しましょう。

def log(msg):
    print(msg)  # None が返る(副作用のみ)
Python

副作用を減らす設計(ミュータブルの扱い・コピー・純粋関数)

ミュータブル引数を書き換えない

リストや辞書を直接変更すると呼び出し元に影響します。新しい値を作って返す設計が安全です。

def add_user(users, name):
    return users + [name]  # 元を壊さず新リストを返す
Python

どうしても書き換えるなら意図を明記し、必要ならコピー

関数名・docstring で副作用を明言。安全にしたいなら内部でコピーを作るか、呼び出し側にコピーを渡してもらう運用にします。

def add_tag_inplace(post, tag):
    """post['tags'] を直接変更する(副作用あり)"""
    post.setdefault("tags", []).append(tag)
Python

純粋関数志向でテスト容易性を高める

「同じ入力なら常に同じ出力で、外部状態を変えない」関数はテストが簡単で再利用性が高くなります。副作用は外へ分離しましょう。

型ヒントとドキュメンテーション(意図を明確にする)

型ヒントで入出力を宣言する

実行時強制ではないが、IDE補完・静的解析・レビュー品質が上がります。特に返り値の型が重要です。

from typing import Iterable, Tuple

def mean_and_sum(nums: Iterable[float]) -> Tuple[float, float]:
    total = sum(nums)
    count = sum(1 for _ in nums)  # 注意:イテレータは消費される
    # 実務では list(nums) にするか、2回走査しない設計へ
    return (total / count, total) if count else (0.0, 0.0)
Python

docstring で「何を・何を受け取り・何を返すか」を書く

将来の自分と他人への説明書。例外や副作用もここで宣言するとトラブルが減ります。

def normalize(name: str, *, lower=True) -> str:
    """名前の前後空白を取り、必要なら小文字化する。
    lower: True なら小文字化
    """
    s = name.strip()
    return s.lower() if lower else s
Python

実践例(定番から一歩先まで)

入力検証+明確な返り値(成功/失敗を区別)

def parse_int(text: str) -> tuple[bool, int | None]:
    s = text.strip()
    if s.isdigit():
        return True, int(s)
    return False, None

ok, value = parse_int(" 25 ")
Python

キーワード限定で堅牢な API

def format_price(amount: int, *, currency: str = "JPY", with_tax: bool = False) -> str:
    total = round(amount * (1.1 if with_tax else 1))
    return f"{currency} {total}"

print(format_price(350))
print(format_price(350, with_tax=True))
Python

集計関数(副作用なし・複数返り値)

def revenue_stats(orders: list[dict]) -> tuple[int, float]:
    totals = [o["qty"] * o["price"] for o in orders]
    total = sum(totals)
    avg = total / len(totals) if totals else 0.0
    return total, avg
Python

*args と **kwargs で拡張可能なレンダラ

def render_button(label: str, *classes: str, **attrs) -> str:
    cls = " ".join(classes)
    attr = " ".join(f'{k}="{v}"' for k, v in attrs.items())
    return f'<button class="{cls}" {attr}>{label}</button>'

html = render_button("OK", "primary", id="ok-btn", disabled=True)
Python

まとめ

  • 引数は入口、返り値は出口。データの流れを「引数→処理→return」で明確にする。
  • 位置・キーワード・デフォルトを使い分け、/ と * でインターフェースを堅牢にする。args/*kwargs で拡張性を確保。
  • return は早期終了で読みやすく、複数値はタプル返しが自然。値を返さないなら None を前提に設計。
  • ミュータブルの書き換えは副作用。新しい値を返す設計で安全に。必要なら in-place を明言。
  • 型ヒントと docstring で意図を伝え、テストしやすい純粋関数志向をベースにする。

この基礎を「体で覚える」ために、今書いている関数の引数と返り値を見直してみてください。入口と出口がクリアになるほど、あなたのコードは強く、美しくなります。

タイトルとURLをコピーしました