🇯🇵 日本語 | 🇺🇸 English | 🇪🇸 Español | 🇵🇹 Português | 🇹🇭 ไทย | 🇨🇳 中文

もうKeyErrorで悩まない!Pythonのcollectionsモジュールで、コードをレベルアップしよう

PythonをコマンドプロンプトやPowerShellでPC上で動かすには、Pythonをダウンロードしてインストールする必要があります。
まだの方はPythonのインストールと開発環境の構築の記事を参考にして、Pythonをインストールしてください。

こんにちは! AIの力を借りながら、プログラミング歴数ヶ月で2つのWebサイトを立ち上げた僕です。

今日は、僕がプログラミング学習の初期に「もっと早く知りたかった!」と心から思った、Pythonの超便利機能「collections」モジュールについて、僕自身の失敗談も交えながら分かりやすく解説します。

特に、辞書(`dict`)で`KeyError`というエラーに悩まされた経験がある方や、リスト(`list`)の処理がなんだか遅い…と感じたことがある方には、きっと役立つはずです。この記事を読み終える頃には、あなたのPythonコードが一段とスマートになっていること間違いなし! 専門用語はなるべく使わず、コピペするだけで動くコードをたくさん用意したので、一緒に「動く」を体験していきましょう!


collectionsモジュールって、そもそも何?

「モジュール」なんて聞くと難しく感じるかもしれませんが、要は「Pythonに標準で入っている、便利な道具箱」のようなものです。わざわざ何かをインストールする必要はなく、`import`という一行を書くだけですぐに使えます。

この道具箱の中には、Pythonの基本的なデータ構造である`dict`(辞書)や`list`(リスト)を、さらに強力で使いやすくした特殊な道具たちがたくさん入っています。今回はその中でも、特に僕が「これは使える!」と感動した2つの道具、`defaultdict`と`deque`をピックアップしてご紹介します。


辞書の"うっかり"ミスを防ぐ魔法の箱 `defaultdict`

`defaultdict`がないと、こんなに大変...(僕の失敗談)

皆さんは、辞書(`dict`)を使っていて、こんなエラーに遭遇したことはありませんか?

# 普通の辞書で、存在しないキーにアクセスしようとする
word_counts = {}
# 'apple'というキーはまだ存在しない
word_counts['apple'] += 1 # ここでエラー!

# 実行結果
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# KeyError: 'apple'

これは`KeyError`というエラーで、「そんなキー(鍵)は辞書の中に存在しませんよ!」とPythonに怒られている状態です。僕もWebサイトを作っている時、ユーザーの入力データを処理しようとしてこのエラーに何時間も悩まされました。

このエラーを防ぐには、事前に`if`文でキーが存在するかチェックしたり、`get()`メソッドを使ったりする方法がありますが、コードが少し長くなってしまいますよね。


救世主`defaultdict`の登場!

そんな`KeyError`の悩みを一発で解決してくれるのが`defaultdict`です。これは「存在しないキーにアクセスされた時、自動的に"初期値"を作ってくれる」という魔法のような辞書です。

百聞は一見に如かず。まずはコードを見てみましょう。

from collections import defaultdict

# int を指定すると、初期値が 0 になる defaultdict を作成
word_counts = defaultdict(int)

# 'apple'というキーはまだ存在しない...けど大丈夫!
print(f"アクセス前: {word_counts}") # アクセス前は空
word_counts['apple'] += 1 # エラーが起きない! 自動で word_counts['apple'] = 0 が作られてから +1 される
print(f"アクセス後: {word_counts}")
print(f"appleの数: {word_counts['apple']}")
print(f"orangeの数: {word_counts['orange']}") # 'orange'も存在しないが、アクセスした瞬間に初期値0が返される

すごいですよね! `defaultdict(int)`と書くことで、「もしキーがなかったら、`int()`、つまり`0`を初期値として自動で設定してね」とお願いできます。これで、`KeyError`を心配することなく、いきなり計算を始められるんです。
この挙動は、Pythonの公式ドキュメントでも「キーが存在しない場合にデフォルト値を返す」と説明されており、非常に信頼性の高い機能です。


【コピペで動く】応用例:文章中の単語の出現回数を数える

`defaultdict`が特に活躍するのが、何かの回数を数える時です。例えば、こんな風に文章中の各単語が何回出現するかを簡単にカウントできます。

from collections import defaultdict

sentence = "apple banana apple orange banana apple"
words = sentence.split() # 文章を単語のリストに分割

# int を指定すると、初期値が 0 になる defaultdict
word_counts = defaultdict(int)

for word in words:
  word_counts[word] += 1

# 結果を表示
for word, count in word_counts.items():
  print(f"'{word}': {count}回")

# 普通の辞書に変換して中身を確認することもできる
print(f"\n最終的な辞書の中身: {dict(word_counts)}")

このコードをコピペして実行してみてください。`if`文が一つもなくても、正確に単語数を数えられているのがわかるはずです。これが`defaultdict`の力です!


リストの"遅さ"を解消する超高速な列 `deque`

リストの先頭に追加・削除は、実は苦手

次に紹介するのは`deque`(デックと読みます)です。これは、リスト(`list`)とよく似ていますが、先頭への要素の追加や、先頭からの要素の削除がめちゃくちゃ速いという特徴があります。

実は、Pythonの`list`は、末尾(右端)への追加(`append`)は得意なのですが、先頭(左端)への追加(`insert(0, ...)`)や削除(`pop(0)`)は苦手なんです。

なぜなら、リストの先頭に要素を追加・削除する場合、それ以降のすべての要素を一つずつズラす必要があるからです。これは、たくさんの人が並んでいる列に割り込んだり、先頭の人が抜けたりする時に、後ろの全員が詰めたり下がったりしないといけないのと似ています。要素が増えれば増えるほど、この「ズラす」作業が重くなり、処理が遅くなってしまうのです。


両端の操作ならおまかせ!`deque`の実力

`deque`は、この問題を解決するために作られました。内部の構造が工夫されており(双方向連結リストという仕組みが使われています)、両端での追加・削除なら、要素がどれだけ多くても一瞬で終わります。

これもコードで見てみましょう。リストで行っていた操作が、`deque`ではより直感的なメソッド名で、かつ高速に実行できます。

from collections import deque

# dequeを作成
tasks = deque(['task2', 'task3'])
print(f"初期状態: {tasks}")

# 末尾に要素を追加 (listのappendと同じ)
tasks.append('task4')
print(f"末尾に追加: {tasks}")

# 先頭に要素を追加 (listのinsert(0,...)より高速!)
tasks.appendleft('task1')
print(f"先頭に追加: {tasks}")

# 先頭から要素を削除 (listのpop(0)より高速!)
first_task = tasks.popleft()
print(f"取り出した先頭タスク: {first_task}")
print(f"現在: {tasks}")

【コピペで動く】応用例:最近見た商品リスト(最大件数あり)

`deque`は、タスク管理や履歴の管理に非常に便利です。`maxlen`という機能を使えば、「常に最新のN件だけを保持する」というリストが簡単に作れます。

ECサイトの「最近チェックした商品」機能をイメージしてみてください。

from collections import deque
import time

# 最大5件まで履歴を保持するdequeを作成
history = deque(maxlen=5)

products = ['Tシャツ', 'スニーカー', 'キャップ', 'パーカー', 'ジャケット', 'ショートパンツ']

for product in products:
  print(f"「{product}」を閲覧しました。")
  history.append(product)
  print(f"現在の閲覧履歴: {list(history)}") # list()で変換すると見やすい
  time.sleep(1) # 1秒待つ

print("\n--- 最終的な閲覧履歴 (最新5件) ---")
for item in history:
  print(item)

このコードを実行すると、新しい商品が追加されるたびに、一番古い商品が自動的に押し出されて消えていくのが分かります。これを自前で`list`で実装しようとすると、`if len(list) > 5:`のようなチェックが必要になりますが、`deque(maxlen=N)`ならその必要もありません。スマートですよね!


【体験してみよう】ブラウザで動く単語カウンター

ここまで学んだ`defaultdict`の便利さを、今すぐあなたのブラウザで体験できるサンプルを用意しました。以下のHTMLコードをまるごとコピーして、テキストエディタに貼り付け、「test.html」のような名前で保存してください。そして、そのファイルをブラウザで開いてみましょう。

これはPythonのコードではありませんが、`defaultdict`の「キーがなくても自動で初期化してくれる」という考え方をJavaScriptで再現したものです。テキストエリアに好きな文章を入れて、ボタンを押してみてください!

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>単語カウンター体験</title>
  <style>
    body { font-family: sans-serif; background-color: #202124; color: #e8eaed; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; }
    .container { width: 90%; max-width: 600px; padding: 2rem; border: 1px solid #5f6368; border-radius: 8px; }
    h1 { color: #669df6; }
    textarea { width: 100%; height: 150px; background-color: #3c4043; color: #e8eaed; border: 1px solid #5f6368; border-radius: 4px; padding: 10px; font-size: 1rem; margin-bottom: 1rem; }
    button { background-color: #8ab4f8; color: #202124; border: none; padding: 10px 20px; border-radius: 4px; cursor: pointer; font-weight: bold; }
    button:hover { opacity: 0.9; }
    #result { margin-top: 1.5rem; background-color: #282a2d; padding: 1rem; border-radius: 4px; }
    pre { white-space: pre-wrap; word-wrap: break-word; }
  </style>
</head>
<body>
  <div class="container">
    <h1>単語カウンター</h1>
    <p>下のボックスに文章を入力して、ボタンを押してください。</p>
    <textarea id="text-input" placeholder="ここに文章を入力... (例: apple banana apple orange)"></textarea>
    <button onclick="countWords()">単語の数を数える</button>
    <div id="result">
      <pre>ここに結果が表示されます。</pre>
    </div>
  </div>

  <script>
    function countWords() {
      const text = document.getElementById('text-input').value;
      const resultEl = document.getElementById('result');

      if (!text.trim()) {
        resultEl.innerHTML = '<pre>テキストが入力されていません。</pre>';
        return;
      }

      // スペースや改行で単語に分割し、空の要素を取り除く
      const words = text.toLowerCase().match(/\b(\w+)\b/g) || [];

      // defaultdict(int)の動きを模倣
      const counts = {}; 
      for (const word of words) {
        // キーが存在しなければ0をセットし、その後インクリメント
        counts[word] = (counts[word] || 0) + 1;
      }

      // 結果を整形して表示
      let resultText = '【カウント結果】\n';
      for (const [word, count] of Object.entries(counts)) {
        resultText += `"${word}": ${count}回\n`;
      }
      
      resultEl.innerHTML = `<pre>${resultText}</pre>`;
    }
  </script>
</body>
</html>

`collections`を使う上での注意点

最後に、これらの便利な道具を使う上での小さな注意点に触れておきます。


まとめ:賢く使って、一歩先のプログラミングへ

今回は、Pythonの標準ライブラリ「`collections`」モジュールから、特に初心者のうちから知っておくと便利な`defaultdict`と`deque`を紹介しました。

僕自身、これらの存在を知ってから、コードがシンプルになり、エラーに悩む時間も格段に減りました。皆さんも、まずはこの記事のコードをコピペして動かしてみることから始めて、その便利さを実感してみてください。基本的な`list`や`dict`を使いこなすのも大切ですが、`collections`のような便利な道具を適材適所で使うことで、より効率的で読みやすいコードが書けるようになりますよ!

次のステップへ

`collections`モジュールの便利さを体験した次は、実際にテキストベースのアプリケーション作成に挑戦してみませんか?基本的なデータ構造を使って、動くものを作る楽しさを味わってみましょう!

PythonでToDoリストアプリを作ろう(テキストベース)