メインコンテンツへスキップ
Lesson4 / 8

キーワード引数

目次

1. このレッスンで学ぶこと

  • キーワード引数とは何か
  • キーワード引数の使い方
  • 位置引数との違い
  • キーワード引数のメリット

2. キーワード引数とは

キーワード引数は、引数名を明示的に指定して値を渡す方法です。

構成要素

要素説明
引数名パラメータの名前name, age
渡す値"太郎", 25
位置引数順序で渡す引数func(10, 20)
キーワード引数名前で渡す引数func(a=10, b=20)

主な特徴

  • 引数名を指定して値を渡せる
  • 引数の順序を気にしなくてよい
  • コードの可読性が向上する
  • デフォルト引数と組み合わせて使える

シンプルな例

Python
# キーワード引数を受け取る関数
def introduce(name, age, city):
    print(f"私は{name}です")
    print(f"{age}歳、{city}在住です")

# キーワード引数で呼び出し
introduce(name="太郎", age=25, city="東京")

# 順序を変えてもOK
introduce(city="大阪", name="花子", age=30)

実行結果:

私は太郎です
25歳、東京在住です
私は花子です
30歳、大阪在住です

3. なぜキーワード引数が必要か?

引数が多い関数では、順序を覚えるのが大変です。

Python
# 位置引数だけ(順序を間違えやすい)
create_user("太郎", 25, "taro@example.com", "Tokyo")

# キーワード引数(分かりやすい)
create_user(name="太郎", age=25, email="taro@example.com", city="Tokyo")

# 順序を気にしなくてOK
create_user(email="taro@example.com", city="Tokyo", name="太郎", age=25)

キーワード引数を使うことで、コードが読みやすくなります。

💡 豆知識: キーワード引数は「名前付き引数」とも呼ばれます。Pythonでは位置引数とキーワード引数を混在させることができ、これが非常に柔軟なAPIを作ることを可能にしています。多くのPython標準ライブラリでもこのパターンが使われています。


4. 位置引数とキーワード引数の混在

Python
def create_user(name, age, email, city="Tokyo", premium=False):
    user = {
        "name": name,
        "age": age,
        "email": email,
        "city": city,
        "premium": premium
    }
    return user

# 位置引数のみ
user1 = create_user("太郎", 25, "taro@example.com")
print(f"ユーザー1: {user1}")

# 位置引数 + キーワード引数
user2 = create_user("花子", 30, "hanako@example.com", city="大阪")
print(f"ユーザー2: {user2}")

# 位置引数 + 複数のキーワード引数
user3 = create_user("次郎", 28, "jiro@example.com",
                    city="福岡", premium=True)
print(f"ユーザー3: {user3}")

# 全てキーワード引数
user4 = create_user(name="三郎", age=35,
                    email="saburo@example.com",
                    city="名古屋", premium=True)
print(f"ユーザー4: {user4}")

実行結果:

ユーザー1: {'name': '太郎', 'age': 25, 'email': 'taro@example.com', 'city': 'Tokyo', 'premium': False}
ユーザー2: {'name': '花子', 'age': 30, 'email': 'hanako@example.com', 'city': '大阪', 'premium': False}
ユーザー3: {'name': '次郎', 'age': 28, 'email': 'jiro@example.com', 'city': '福岡', 'premium': True}
ユーザー4: {'name': '三郎', 'age': 35, 'email': 'saburo@example.com', 'city': '名古屋', 'premium': True}

5. キーワード引数のメリット

メリット1: 可読性の向上

Python
# 位置引数だけ(何の値か分かりにくい)
def send_email(to, subject, body, cc, bcc, priority):
    print(f"To: {to}")
    print(f"件名: {subject}")
    print(f"本文: {body}")
    print(f"CC: {cc}, BCC: {bcc}, 優先度: {priority}")

# 分かりにくい
send_email("taro@example.com", "会議のお知らせ", "明日の会議...",
           "hanako@example.com", "", 1)

print()

# キーワード引数(分かりやすい)
send_email(
    to="taro@example.com",
    subject="会議のお知らせ",
    body="明日の会議について",
    cc="hanako@example.com",
    bcc="",
    priority=1
)

実行結果:

To: taro@example.com
件名: 会議のお知らせ
本文: 明日の会議...
CC: hanako@example.com, BCC: , 優先度: 1

To: taro@example.com
件名: 会議のお知らせ
本文: 明日の会議について
CC: hanako@example.com, BCC: , 優先度: 1

メリット2: デフォルト値を部分的に上書き

Python
def configure_server(host="localhost", port=8000, debug=False,
                    timeout=30, max_connections=100):
    config = {
        "host": host,
        "port": port,
        "debug": debug,
        "timeout": timeout,
        "max_connections": max_connections
    }
    return config

# 必要な部分だけ変更
config1 = configure_server(debug=True)
print(f"開発環境: {config1}")

# 特定の設定だけ変更
config2 = configure_server(host="0.0.0.0", port=80)
print(f"本番環境: {config2}")

# 複数の設定を変更
config3 = configure_server(port=3000, timeout=60, max_connections=200)
print(f"カスタム: {config3}")

実行結果:

開発環境: {'host': 'localhost', 'port': 8000, 'debug': True, 'timeout': 30, 'max_connections': 100}
本番環境: {'host': '0.0.0.0', 'port': 80, 'debug': False, 'timeout': 30, 'max_connections': 100}
カスタム: {'host': 'localhost', 'port': 3000, 'debug': False, 'timeout': 60, 'max_connections': 200}

メリット3: 引数の順序を気にしない

Python
def draw_rectangle(x, y, width, height, color="black", thickness=1):
    print(f"座標: ({x}, {y})")
    print(f"サイズ: {width} x {height}")
    print(f"色: {color}, 線の太さ: {thickness}")

# 順序通り
draw_rectangle(10, 20, 100, 50, "red", 2)
print()

# 順序を変えて指定
draw_rectangle(10, 20, 100, 50, thickness=3, color="blue")
print()

# 必須引数だけキーワードで
draw_rectangle(x=0, y=0, width=200, height=100)

実行結果:

座標: (10, 20)
サイズ: 100 x 50
色: red, 線の太さ: 2

座標: (10, 20)
サイズ: 100 x 50
色: blue, 線の太さ: 3

座標: (0, 0)
サイズ: 200 x 100
色: black, 線の太さ: 1

6. キーワード専用引数

アスタリスク(*)の使用

機能: アスタリスク以降の引数はキーワードでのみ指定可能にします。

書き方:

Python
def 関数名(位置引数, *, キーワード専用引数):
    処理

用途: 引数の誤用を防ぐ

注意点: *以降は必ずキーワードで指定

Python
def create_file(filename, *, mode="w", encoding="utf-8", backup=False):
    """
    ファイルを作成
    filename: 位置引数
    mode, encoding, backup: キーワード専用
    """
    print(f"ファイル作成: {filename}")
    print(f"  モード: {mode}")
    print(f"  エンコーディング: {encoding}")
    print(f"  バックアップ: {backup}")

# 正しい使い方
create_file("data.txt")
print()

create_file("data.txt", mode="a")
print()

create_file("data.txt", encoding="shift-jis", backup=True)
print()

# 間違った使い方(エラー)
# create_file("data.txt", "a", "utf-8")  # TypeError!

実行結果:

ファイル作成: data.txt
  モード: w
  エンコーディング: utf-8
  バックアップ: False

ファイル作成: data.txt
  モード: a
  エンコーディング: utf-8
  バックアップ: False

ファイル作成: data.txt
  モード: w
  エンコーディング: shift-jis
  バックアップ: True

7. 具体例

例1: データベースクエリ

Python
def query_users(limit=10, offset=0, order_by="id", ascending=True,
                active_only=False):
    """ユーザーを検索"""
    direction = "ASC" if ascending else "DESC"
    active_filter = "AND active=1" if active_only else ""

    query = f"""
    SELECT * FROM users
    WHERE 1=1 {active_filter}
    ORDER BY {order_by} {direction}
    LIMIT {limit} OFFSET {offset}
    """

    print(query.strip())
    return query

# デフォルト設定
print("=== クエリ1 ===")
query_users()

print("\n=== クエリ2 ===")
# ページング
query_users(limit=20, offset=40)

print("\n=== クエリ3 ===")
# ソート変更
query_users(order_by="created_at", ascending=False)

print("\n=== クエリ4 ===")
# アクティブユーザーのみ
query_users(active_only=True, limit=5)

実行結果:

=== クエリ1 ===
SELECT * FROM users
    WHERE 1=1
    ORDER BY id ASC
    LIMIT 10 OFFSET 0

=== クエリ2 ===
SELECT * FROM users
    WHERE 1=1
    ORDER BY id ASC
    LIMIT 20 OFFSET 40

=== クエリ3 ===
SELECT * FROM users
    WHERE 1=1
    ORDER BY created_at DESC
    LIMIT 10 OFFSET 0

=== クエリ4 ===
SELECT * FROM users
    WHERE 1=1 AND active=1
    ORDER BY id ASC
    LIMIT 5 OFFSET 0

例2: API リクエスト

Python
def api_request(endpoint, method="GET", headers=None, params=None,
                data=None, timeout=30, retry=3):
    """APIリクエストを送信(シミュレーション)"""
    print(f"=== APIリクエスト ===")
    print(f"エンドポイント: {endpoint}")
    print(f"メソッド: {method}")
    print(f"タイムアウト: {timeout}秒")
    print(f"リトライ回数: {retry}回")

    if headers:
        print(f"ヘッダー: {headers}")
    if params:
        print(f"パラメータ: {params}")
    if data:
        print(f"データ: {data}")

# GETリクエスト
api_request("/api/users")
print()

# パラメータ付きGET
api_request(
    "/api/users",
    params={"page": 1, "limit": 20}
)
print()

# POSTリクエスト
api_request(
    endpoint="/api/users",
    method="POST",
    headers={"Content-Type": "application/json"},
    data={"name": "太郎", "email": "taro@example.com"},
    timeout=60
)

実行結果:

=== APIリクエスト ===
エンドポイント: /api/users
メソッド: GET
タイムアウト: 30秒
リトライ回数: 3回

=== APIリクエスト ===
エンドポイント: /api/users
メソッド: GET
タイムアウト: 30秒
リトライ回数: 3回
パラメータ: {'page': 1, 'limit': 20}

=== APIリクエスト ===
エンドポイント: /api/users
メソッド: POST
タイムアウト: 60秒
リトライ回数: 3回
ヘッダー: {'Content-Type': 'application/json'}
データ: {'name': '太郎', 'email': 'taro@example.com'}

例3: レポート生成

Python
def generate_report(data, *, title="レポート", format="PDF",
                   include_chart=True, include_summary=True,
                   page_size="A4", orientation="portrait"):
    """レポートを生成"""
    print(f"{'='*50}")
    print(f"レポート: {title}")
    print(f"{'='*50}")
    print(f"形式: {format}")
    print(f"ページサイズ: {page_size}")
    print(f"向き: {orientation}")
    print(f"グラフ: {'あり' if include_chart else 'なし'}")
    print(f"サマリー: {'あり' if include_summary else 'なし'}")
    print(f"\nデータ件数: {len(data)}件")
    print(f"{'='*50}")

sales_data = [100, 200, 150, 300, 250]

# 基本レポート
generate_report(sales_data, title="月次売上レポート")
print()

# カスタマイズ
generate_report(
    sales_data,
    title="年次報告書",
    format="Excel",
    page_size="A3",
    orientation="landscape",
    include_chart=False
)

実行結果:

==================================================
レポート: 月次売上レポート
==================================================
形式: PDF
ページサイズ: A4
向き: portrait
グラフ: あり
サマリー: あり

データ件数: 5件
==================================================

==================================================
レポート: 年次報告書
==================================================
形式: Excel
ページサイズ: A3
向き: landscape
グラフ: なし
サマリー: あり

データ件数: 5件
==================================================

8. 練習問題

問題1(基礎)⭐☆☆

名前、年齢、都市の3つの引数を受け取る関数 show_profile を作成してください。この関数は「名前: 〇〇、年齢: △△歳、都市: □□」という形式で情報を表示します。関数をキーワード引数で呼び出し、引数の順序を変えて呼び出してください。

💡 ヒント
  1. def show_profile(name, age, city): で関数を定義
  2. f-stringを使って情報を整形
  3. print() で表示
  4. show_profile(name="太郎", age=25, city="東京") のようにキーワード引数で呼び出す
  5. show_profile(city="大阪", name="花子", age=30) のように順序を変えて呼び出す
✅ 解答例
Python
def show_profile(name, age, city):
    print(f"名前: {name}、年齢: {age}歳、都市: {city}")

# キーワード引数で呼び出し(通常の順序)
show_profile(name="太郎", age=25, city="東京")

# キーワード引数で呼び出し(順序を変更)
show_profile(city="大阪", name="花子", age=30)
show_profile(age=28, city="福岡", name="次郎")

実行結果:

名前: 太郎、年齢: 25歳、都市: 東京
名前: 花子、年齢: 30歳、都市: 大阪
名前: 次郎、年齢: 28歳、都市: 福岡

解説: キーワード引数を使うと、引数の順序を気にせずに関数を呼び出せます。show_profile(city="大阪", name="花子", age=30) のように順序を変えても、引数名で値が正しく対応付けられます。


問題2(基礎)⭐☆☆

商品名を必須引数、価格をデフォルト引数(初期値 1000)、在庫数をデフォルト引数(初期値 0)として受け取る関数 show_product を作成してください。以下の3つの呼び出し方を試してください:

  1. 商品名のみ指定
  2. 商品名と価格を位置引数で指定
  3. 商品名を位置引数、在庫数をキーワード引数で指定
💡 ヒント
  1. def show_product(name, price=1000, stock=0): で関数を定義
  2. f-stringを使って商品情報を表示
  3. show_product("りんご") で商品名のみ
  4. show_product("バナナ", 500) で商品名と価格を位置引数で指定
  5. show_product("オレンジ", stock=10) で商品名を位置、在庫をキーワードで指定
✅ 解答例
Python
def show_product(name, price=1000, stock=0):
    print(f"商品: {name}、価格: {price}円、在庫: {stock}個")

# 1. 商品名のみ指定(デフォルト値を使用)
show_product("りんご")

# 2. 商品名と価格を位置引数で指定
show_product("バナナ", 500)

# 3. 商品名を位置引数、在庫数をキーワード引数で指定
show_product("オレンジ", stock=10)

実行結果:

商品: りんご、価格: 1000円、在庫: 0個
商品: バナナ、価格: 500円、在庫: 0個
商品: オレンジ、価格: 1000円、在庫: 10個

解説: 位置引数とキーワード引数を混在させることができます。show_product("オレンジ", stock=10) では、name は位置引数で渡し、stock はキーワード引数で指定しています。この場合、price はデフォルト値の 1000 が使われます。キーワード引数を使うことで、途中の引数をスキップして後ろの引数だけを指定できます。


問題3(応用)⭐⭐☆

タイトルを必須引数、ファイル形式、ページサイズ、向きをキーワード専用引数(* を使用)として受け取る関数 create_document を作成してください。キーワード専用引数のデフォルト値は以下の通りです:

  • format: "PDF"
  • page_size: "A4"
  • orientation: "portrait"

この関数は、ドキュメント情報を表示します。以下の2つの呼び出し方を試してください:

  1. タイトルのみ指定
  2. タイトルと一部のキーワード専用引数を指定
💡 ヒント
  1. def create_document(title, *, format="PDF", page_size="A4", orientation="portrait"): で関数を定義
  2. * の後の引数はキーワードでのみ指定可能
  3. f-stringを使ってドキュメント情報を表示
  4. create_document("報告書") でタイトルのみ
  5. create_document("提案書", format="Word", page_size="A3") で一部のキーワード引数を指定
✅ 解答例
Python
def create_document(title, *, format="PDF", page_size="A4", orientation="portrait"):
    print(f"ドキュメント作成:")
    print(f"  タイトル: {title}")
    print(f"  形式: {format}")
    print(f"  ページサイズ: {page_size}")
    print(f"  向き: {orientation}")

# 1. タイトルのみ指定(すべてデフォルト値)
create_document("報告書")
print()

# 2. タイトルと一部のキーワード専用引数を指定
create_document("提案書", format="Word", page_size="A3")
print()

# 3. すべての引数を指定
create_document("年次レポート", format="Excel", page_size="A4", orientation="landscape")

実行結果:

ドキュメント作成:
  タイトル: 報告書
  形式: PDF
  ページサイズ: A4
  向き: portrait

ドキュメント作成:
  タイトル: 提案書
  形式: Word
  ページサイズ: A3
  向き: portrait

ドキュメント作成:
  タイトル: 年次レポート
  形式: Excel
  ページサイズ: A4
  向き: landscape

解説: * を使うことで、それ以降の引数をキーワード専用にできます。def create_document(title, *, format="PDF", ...) では、title は位置引数またはキーワード引数で指定できますが、formatpage_sizeorientation は必ずキーワードで指定する必要があります。これにより、create_document("報告書", "Word") のような誤った呼び出しを防ぐことができ、コードの可読性と安全性が向上します。


9. まとめ

このレッスンでは、キーワード引数で可読性を高める方法を学びました。

  • 引数名を明示することで、呼び出し意図を明確にできます。
  • 位置引数とキーワード引数の併用ルールを理解しました。
  • 順序に依存しない呼び出しで、保守しやすいコードを書けます。
  • 多数の引数を持つ関数で特に有効であることを確認しました。
  • 呼び出し側の読みやすさを優先する設計の重要性を学びました。