← Python言語ページに戻る
🐍

Pythonサンプルコード集

文法解説で学んだ内容を組み合わせた、難易度が段階的に上がる3本の実践的なサンプルプログラムです。①基本文法を組み合わせた在庫管理アプリ、②アルゴリズム・データ構造を使った成績データ処理、③デコレータとジェネレータを使った発展的なログ処理、の順に見ていきましょう。

① 在庫管理アプリ(クラス・辞書・例外処理)

クラスによるカプセル化、辞書を使ったデータ保持、カスタム例外による入力チェックを組み合わせた小規模アプリです。Inventoryクラスが在庫の追加・出庫・レポート出力を担当し、在庫不足や存在しない商品名の指定は独自の例外クラスで通知します。

SAMPLE PROGRAM
class ItemNotFoundError(Exception):
    """在庫に存在しない商品を指定したときの例外"""
    pass


class InsufficientStockError(Exception):
    """在庫数が不足しているときの例外"""
    pass


class Inventory:
    def __init__(self):
        self._items = {}   # {商品名: 数量}

    def add(self, name, qty):
        self._items[name] = self._items.get(name, 0) + qty

    def remove(self, name, qty):
        if name not in self._items:
            raise ItemNotFoundError(f"「{name}」は在庫にありません")
        if self._items[name] < qty:
            raise InsufficientStockError(
                f"「{name}」の在庫が{self._items[name]}個しかありません(要求: {qty}個)"
            )
        self._items[name] -= qty

    def report(self):
        return [f"{name}: {qty}個" for name, qty in sorted(self._items.items())]


def main():
    inv = Inventory()
    inv.add("ノート", 10)
    inv.add("消しゴム", 5)
    inv.add("ノート", 3)   # 同じ商品を追加すると数量が加算される

    orders = [("ノート", 5), ("鉛筆", 1), ("消しゴム", 100)]

    for name, qty in orders:
        try:
            inv.remove(name, qty)
            print(f"出庫成功: {name} x {qty}")
        except ItemNotFoundError as e:
            print(f"エラー: {e}")
        except InsufficientStockError as e:
            print(f"エラー: {e}")

    print("--- 在庫レポート ---")
    for line in inv.report():
        print(line)


if __name__ == "__main__":
    main()

② 成績データの整列・検索(クイックソート・二分探索)

文法解説で紹介したクイックソート(平均計算量O(n log n))とdataclassを使って、複数の学生の点数データを整列し、二分探索(計算量O(log n))で特定の点数を検索する例です。データ量が多いほど、線形探索(O(n))よりも「まずソートして二分探索」の方が高速に検索できます。

SAMPLE PROGRAM
from dataclasses import dataclass


@dataclass
class Student:
    name: str
    score: int

    def __lt__(self, other):
        # ソート・比較で使われる特殊メソッド
        return self.score < other.score


def quick_sort(students):
    if len(students) <= 1:
        return students
    pivot = students[len(students) // 2]
    left = [s for s in students if s < pivot]
    mid = [s for s in students if s.score == pivot.score]
    right = [s for s in students if pivot < s]
    return quick_sort(left) + mid + quick_sort(right)


def binary_search_by_score(sorted_students, target_score):
    """点数でソート済みのリストから二分探索する。計算量 O(log n)"""
    low, high = 0, len(sorted_students) - 1
    while low <= high:
        mid = (low + high) // 2
        if sorted_students[mid].score == target_score:
            return sorted_students[mid]
        elif sorted_students[mid].score < target_score:
            low = mid + 1
        else:
            high = mid - 1
    return None


students = [
    Student("佐藤", 72),
    Student("鈴木", 95),
    Student("高橋", 60),
    Student("田中", 88),
    Student("伊藤", 79),
]

sorted_students = quick_sort(students)
print("--- 点数順(昇順) ---")
for s in sorted_students:
    print(f"{s.name}: {s.score}点")

found = binary_search_by_score(sorted_students, 88)
print("検索結果:", found)   # Student(name='田中', score=88)

③ アクセスログ集計(デコレータとジェネレータ)

大量のログ行を1行ずつ処理するジェネレータ関数と、処理時間を計測するデコレータを組み合わせた発展的な例です。ジェネレータを使うことで、ログファイル全体を一度にメモリに読み込まずに済み、大きなファイルでもメモリ効率よく処理できます。

SAMPLE PROGRAM
import time
from functools import wraps
from collections import Counter


def timer(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start = time.perf_counter()
        result = func(*args, **kwargs)
        print(f"[{func.__name__}] 実行時間: {time.perf_counter() - start:.6f}秒")
        return result
    return wrapper


def read_log_lines(lines):
    """本来はファイルを1行ずつ読むが、ここではサンプル用に擬似ログを生成するジェネレータ"""
    for line in lines:
        yield line.strip()


def parse_status_code(line):
    # 例: "2026-07-05 GET /index.html 200"
    return line.split()[-1]


@timer
def count_status_codes(log_lines):
    counter = Counter()
    for line in read_log_lines(log_lines):   # ジェネレータを1行ずつ消費する
        status = parse_status_code(line)
        counter[status] += 1
    return counter


sample_logs = [
    "2026-07-05 GET /index.html 200",
    "2026-07-05 GET /pages/python.html 200",
    "2026-07-05 GET /missing.html 404",
    "2026-07-05 POST /api/login 200",
    "2026-07-05 GET /api/data 500",
]

result = count_status_codes(sample_logs)
for status, count in result.most_common():
    print(f"ステータス{status}: {count}件")
理解度チェッククイズに挑戦する →