概要(**kwargs は「名前付きの任意個の引数」を辞書で受け取る仕組み)
**kwargs は、関数に渡された「キーワード引数(名前=値)」を、任意の個数まとめて受け取るための記法です。関数内では普通の辞書(dict)として扱えます。固定のオプションだけでなく、将来増えるかもしれない設定を柔軟に受けるときに役立ちます。
def show_info(**kwargs):
print(kwargs, type(kwargs))
show_info(name="Hanako", age=20) # {'name': 'Hanako', 'age': 20} <class 'dict'>
Python基本構文と並び順(ここが重要)
固定引数・args・キーワード固定・*kwargs の順序
関数定義では、必ず「位置引数 → *args → キーワード引数 → **kwargs」の順に並べます。順序が崩れるとエラーになります。
def render(label, *classes, id=None, **attrs):
cls = " ".join(classes)
extra = " ".join(f'{k}="{v}"' for k, v in attrs.items())
return f'<button id="{id}" class="{cls}" {extra}>{label}</button>'
print(render("OK", "primary", "rounded", id="ok", disabled=True))
Python受け取りは辞書、その場で展開もできる
kwargs で受けた辞書はそのまま別関数へ「」で展開できます。ラッパ関数やフォワーディングに向いています。
def base_connect(host, port, secure=False, timeout=3):
return (host, port, secure, timeout)
def connect_with_defaults(**kwargs):
kwargs.setdefault("secure", True) # 欠けていれば補う
kwargs.setdefault("timeout", 5)
return base_connect(**kwargs)
print(connect_with_defaults(host="example.com", port=443))
Python具体的な使いどころ(拡張性・前処理・検証)
将来のオプション追加に強い API を作る
公開関数で受け取れるオプションが増えても、**kwargs なら既存の呼び出しは壊れません。必要なキーだけ取り出し、残りは無視する設計にできます。
def format_price(amount, **options):
currency = options.get("currency", "JPY")
tax_rate = options.get("tax_rate", 0.1)
total = round(amount * (1 + tax_rate))
return f"{currency} {total}"
print(format_price(350))
print(format_price(350, tax_rate=0.08))
Pythonバリデーション(許可キー・型チェック)
受け取りが自由な分、早めのチェックで利用者の間違いを検出します。わかりやすいエラーメッセージが命です。
def save_user(**kwargs):
allowed = {"name", "email", "age"}
unknown = set(kwargs) - allowed
if unknown:
raise ValueError(f"未許可のキー: {', '.join(sorted(unknown))}")
if "email" in kwargs and "@" not in kwargs["email"]:
raise ValueError("email の形式が不正です")
# ここで保存処理…
return kwargs
Python前処理+委譲(変換してから渡す)
到着したキーワードを正規化して、別関数へ委譲。責務分離で読みやすく、テストしやすくなります。
def normalize_opts(**kwargs):
if "case" in kwargs:
kwargs["case"] = kwargs["case"].lower()
return kwargs
def process(text, **kwargs):
opts = normalize_opts(**kwargs)
if opts.get("case") == "upper":
text = text.upper()
elif opts.get("case") == "lower":
text = text.lower()
return text
print(process("Coffee", case="UPPER"))
Python設計の勘所(使うべき場面と避ける場面を深掘り)
**kwargs を使うべき場面
- オプションが多い、または増える見込みがある
- 呼び出し側から柔軟な設定を受けたい(ログ、レンダリング、フォーマッタなど)
- ライブラリのラッパで「未使用のオプションも受けてそのまま渡す」設計
**kwargs を避ける場面
- 必須の引数や意味が確定した少数のオプションは、名前付き引数として明示した方が読みやすい
- 何でも受けすぎると「何が使えるのか」が不透明になる。docstring と検証で輪郭をはっきりさせる
位置限定/キーワード限定との併用
API を壊さないための作法として、「/ の左は位置のみ」「* の右はキーワードのみ」を使うと、意図しない呼び出しを防げます。
def api(user_id, /, *, page=1, limit=20, **extra):
# user_id は位置のみ、page/limit はキーワードのみ、extra は将来用
return {"user_id": user_id, "page": page, "limit": limit, **extra}
実践例(現場ですぐ使えるパターン)
HTML 属性の合成(未指定はスキップ)
def tag(name, **attrs):
parts = [f'{k}="{v}"' for k, v in attrs.items() if v is not None]
return f"<{name} {' '.join(parts)}></{name}>"
print(tag("div", id="main", data_role="dialog"))
Pythonログ関数(レベル・タグ・メタを柔軟に)
def log(*parts, **meta):
level = meta.pop("level", "INFO")
msg = " ".join(map(str, parts))
extras = " ".join(f'{k}={v}' for k, v in meta.items())
print(f"[{level}] {msg} {extras}".strip())
log("start", level="INFO", job="batch", try=1)
Python検索 API のラッパ(未知オプションを透過)
def base_search(query, **options):
# 実際の検索機構へ options を渡す
return {"q": query, "options": options}
def search(query, **kwargs):
# 既定値を補ってから委譲
kwargs.setdefault("limit", 20)
kwargs.setdefault("case_insensitive", True)
return base_search(query, **kwargs)
print(search("coffee", limit=5))
Pythonつまずきやすいポイントと対策
キーワード指定でしか渡せない
**kwargs は「名前=値」で渡す前提。位置引数は *args で受けるか、固定引数にする。混同すると TypeError の原因になります。
受けたまま丸投げは危険
その関数が知らない・対応していないオプションまで丸投げすると、下流で落ちます。許可リスト・置換・削除で整えてから渡すのが安全です。
型ヒントと docstring で意図を明確化
「受ける可能性のあるキー」と「既定値・型」をドキュメントに書く。主要キーは引数として明示し、残りを **kwargs にするのがバランス良いです。
def resize(width: int, height: int, *, keep_ratio: bool = True, **opts) -> dict:
"""画像をリサイズする。主要オプション:
keep_ratio: アスペクト比維持(既定 True)
その他のオプションは **opts で受ける
"""
bg = opts.get("background", "black")
return {"w": width, "h": height, "keep": keep_ratio, "bg": bg}
Python例題で身につける(定番から一歩先まで)
例題1:必須+拡張オプション
def export(path, **opts):
fmt = opts.get("format", "csv")
compress = opts.get("compress", False)
return {"path": path, "format": fmt, "compress": compress}
print(export("out/data"))
print(export("out/data", format="json", compress=True))
Python例題2:許可キーのバリデーション
def schedule(task, **opts):
allowed = {"at", "retry", "timeout"}
bad = set(opts) - allowed
if bad:
raise ValueError(f"未知のオプション: {', '.join(bad)}")
return {"task": task, **opts}
print(schedule("backup", at="02:00", retry=3))
Python例題3:フォーマッタ(欠損補完+処理切り替え)
def format_text(text, **opts):
opts.setdefault("case", "lower")
s = text.strip()
if opts["case"] == "upper":
s = s.upper()
elif opts["case"] == "lower":
s = s.lower()
width = opts.get("width")
return s[:width] if width else s
print(format_text(" Coffee ", width=6, case="upper")) # 'COFFEE'
Python例題4:プロキシでそのまま透過(必要な置換のみ)
def fetch(url, **kwargs):
kwargs.setdefault("timeout", 5)
if "headers" in kwargs and "User-Agent" not in kwargs["headers"]:
kwargs["headers"]["User-Agent"] = "MyClient/1.0"
return {"url": url, "opts": kwargs}
print(fetch("https://example.com", headers={"Accept": "application/json"}))
Pythonまとめ
kwargs は「名前付き引数を辞書で任意個受ける」ための強力な仕組みです。固定・args・キーワード固定・*kwargs の順序を守り、主要オプションは引数として明示、拡張可能な部分は **kwargs に逃がす。受けたら早めにバリデーション・既定値補完・正規化を行い、必要に応じて委譲で再利用する。ドキュメントと型ヒントで「何が受け取れるのか」を伝えれば、初心者でも安全で拡張性の高い関数インターフェースを設計できます。
