Python
 Computer >> コンピューター >  >> プログラミング >> Python

Pythonコレクション徹底解説:collectionsモジュールの使い方をステップバイステップで学ぶ

Pythonには、リスト・タプル・セット・辞書という4つの基本的なデータコレクション型が用意されています。さらに、標準ライブラリのcollectionsモジュールを活用すれば、namedtupleCounterdefaultdictChainMapといった便利な特殊データ構造も利用できるようになります。

Pythonの4つのコレクション型は、それぞれ特定の場面で威力を発揮します。たとえば、後から内容を書き換えたい生徒名簿のようなデータには変更可能なリストが適しています。一方、絶対に変わらないアイスクリームのフレーバー一覧のようなデータなら、内容を変更できないタプルの方がふさわしいでしょう。

しかし、実際にPythonで開発を進めていると、組み込みのコレクション型だけでは目的の機能が足りない場面に出くわすことがあります。そんなときに頼りになるのが、より高度なデータ操作を可能にする「collections」モジュールです。

collectionsモジュールは、組み込みコレクションの機能を拡張し、開発者がデータ構造をより柔軟に扱えるよう設計されました。本ガイドでは、collectionsモジュールの基本を解説し、特によく使われる4つのデータ構造を具体例とともに紹介します。

コレクションのおさらい

コレクションとは、データを格納するためのコンテナ型データのことです。冒頭で触れたとおり、リスト・セット・タプル・辞書の4種類があり、それぞれ異なる特性を持っています。

リスト(List)

リストは順序付き・変更可能なデータ型で、時間とともに変化しうるデータの保存に向いています。要素の追加・削除・更新が自由に行え、重複した値も保持できます。インデックス番号を使って個々の要素へアクセスするのも簡単です。

Pythonでリストを宣言する例:

sandwiches = ["Cheese", "Ham", "Tuna", "Egg Mayo"]

タプル(Tuple)

タプルは順序付き・不変(immutable)なデータ型です。重複した値を含めることはできますが、一度作成すると値を変更できません。丸括弧 () で囲んで宣言します。

Pythonのタプルの例:

sandwiches = ("Cheese", "Ham", "Tuna", "Egg Mayo")

セット(Set)

セットは順序を持たないコレクションです。波括弧 {} を使って宣言します。リストと異なりインデックスが存在せず、重複した要素は自動的に除外される点が大きな特徴です。

Pythonのセットの例:

sandwiches = {"Cheese", "Ham", "Tuna", "Egg Mayo"}

辞書(Dictionary)

辞書は変更可能で、キーと値のペアによってデータを管理するデータ型です(Python 3.7以降では挿入順が保持されます)。各要素は一意なキーで参照できます。

Pythonの辞書の例:

sandwich = {
	"name": "Cheese",
	"price": 8.95
}

これら4つのデータ型はPythonにおいて非常に幅広い用途に活用できますが、より高度な操作を行いたい場合は、collectionsモジュールの検討をおすすめします。

collectionsモジュールとは

collectionsモジュールには、Pythonの組み込みコンテナを補完したり、代替として使えたりする特殊なデータ構造が多数収録されています。collectionsはモジュールであるため、プログラム内でインポートが必要ですが、Python本体に標準で組み込まれているため、外部ライブラリのインストールは一切不要です。

本記事では、collectionsモジュールの中でも特に使用頻度の高い、次の4つのデータ構造に焦点を当てて解説します。

  • Counter
  • namedtuple
  • defaultdict
  • ChainMap

Counter — 要素の出現回数を数える

Counter()は辞書オブジェクトのサブクラスで、ハッシュ可能なオブジェクトの出現回数を数えるために使えます。Counter()関数はイテラブルを引数に取り、結果を辞書として返します。

たとえば、1月のサンドイッチ注文履歴から「BLTサンドイッチが何個売れたか」を調べたいとしましょう。Counter()関数を使えば、この集計は一目瞭然です。

from collections import Counter

sandwich_sales = ["BLT", "Egg Mayo", "Ham", "Ham", "Ham", "Cheese", "BLT", "Cheese"]
our_counter = Counter(sandwich_sales)
print(our_counter["BLT"])

実行結果:2

コードの流れを見てみましょう。

1行目でcollectionsからCounterをインポートします。次に、1月の売上データを格納するsandwich_salesリストを宣言します。続いて、our_counter変数にCounter(sandwich_sales)の結果を代入することで、以降はour_counter経由で集計結果にアクセスできます。

最後にprint(our_counter["BLT"])を実行し、辞書内のBLTに対応する出現回数を出力しています。この例では答えは2でした。

namedtuple — 名前付きフィールドを持つタプル

namedtuple()メソッドは、タプルの各位置に名前を付けたタプルを生成します。通常のタプルではインデックス番号でしか値にアクセスできないため、要素数が多いタプルではどの番号が何を指すのか分かりにくくなりがちです。

namedtuple()を使って、サンドイッチの名前と価格を保存する例を見てみましょう。

from collections import namedtuple

Sandwich = namedtuple("Sandwich", "name, price")
first_sandwich = Sandwich("Chicken Teriyaki", "$3.00")
print(first_sandwich.price)

実行結果:$3.00

コードの解説です。まず1行目でcollectionsモジュールからnamedtupleをインポートします。次に「Sandwich」という名前のタプル型を作成し、「name」と「price」という2つのフィールド名を割り当てます。これにより、後からフィールド名を使ってタプル内の値を参照できるようになります。続いてfirst_sandwich変数を宣言し、「Chicken Teriyaki」のデータを代入します。最後にfirst_sandwich.priceで価格を出力すれば、$3.00が表示されます。

リストからnamedtuple()を生成することも可能です。以下がその例です。

second_sandwich = Sandwich._make(["Spicy Italian", "$3.75"])
print(second_sandwich.name)

実行結果:Spicy Italian。ここではSandwichに対して_makeメソッドを呼び出すことで、リストをnamedtuple()へ変換しています。

defaultdict — KeyErrorを防ぐ辞書

defaultdict()メソッドを使うと、存在しないキーにアクセスしてもKeyErrorを発生させない辞書を作成できます。存在しないキーを参照した場合、事前に指定しておいたデフォルトのデータ型が代わりに返されます。

存在しないキーを参照したときにstr(空文字列)を返す辞書の例です。

from collections import defaultdict

sandwiches = defaultdict(str)
sandwiches[0] = "Ham and Cheese"
sandwiches[1] = "BLT"

print(sandwiches[1])
print(sandwiches[2])

実行結果:

BLT
(空行が出力される)

この例では、インデックス0と1に値を設定した辞書を作成しました。sandwiches[1]を出力すると、登録済みの値が正しく表示されます。一方、値が割り当てられていないsandwiches[2]を出力すると、空文字列(空行)が返ります。

通常の辞書であればここでKeyErrorが発生しますが、defaultdictを使ったことで、辞書作成時に指定したデータ型が返される仕組みです。上記の例ではstrを指定しましたが、整数やその他の任意の有効なデータ型をデフォルトに設定することもできます。

この機能は、複数の項目に対して同じ処理を実行するものの、一部の項目では処理が成立しない可能性があるケースで特に有用です。エラーでプログラムが停止する代わりに、デフォルト値を返しながら処理を継続できます。

ChainMap — 複数の辞書を連結する

ChainMap()メソッドは、2つ以上の辞書を1つにまとめるために使われます。たとえば、「標準メニュー」と「シークレットメニュー」の2つの辞書を、1つの大きなメニューに統合したい場面を考えてみましょう。こうした場合にChainMap()関数が活躍します。

標準メニューとシークレットメニューをマージする例:

from collections import ChainMap

standard_menu = { "BLT": "$3.05", "Roast Beef": "$3.55", "Cheese": "$2.85", "Shrimp": "$3.55", "Ham": "$2.85" }
secret_menu = { "Steak": "$3.60", "Tuna Special": "$3.20", "Turkey Club": "$3.20" }

menu = ChainMap(standard_menu, secret_menu)
print(menu)

実行すると、2つのメニューが統合されたChainMapオブジェクトが返されます。

ChainMap({'BLT': '$3.05', 'Roast Beef': '$3.55', 'Cheese': '$2.85', 'Shrimp': '$3.55', 'Ham': '$2.85'}, {'Steak': '$3.60', 'Tuna Special': '$3.20', 'Turkey Club': '$3.20'})

キー名を指定すれば、ChainMap内の各値にアクセスできます。たとえば、BLTサンドイッチの価格を取得するコードは次のとおりです。

print(menu["BLT"])

実行結果:$3.05

さらに重要なポイントとして、ChainMapは元の辞書と連動して更新される点が挙げられます。standard_menusecret_menuの値を変更すると、ChainMapオブジェクト側にも自動的に反映されます。以下がその例です。

print(menu)
standard_menu["BLT"] = "$3.10"
print(menu)

実行結果を見ると、standard_menu辞書側で価格を変更したことにより、BLTの価格が$3.05から$3.10へと変わっていることが確認できます。

ChainMapオブジェクトには、キーや値を取得するためのメソッドも用意されています。keys()values()メソッドを使うと、それぞれデータのキー一覧(特定の値を参照する際に使用)と、それに紐づく値の一覧を取得できます。

print(list(menu.keys()))
print(list(menu.values()))

これらのメソッドを実行すると、ChainMapオブジェクト内の全項目のキーと値がそれぞれ出力されます。

さらに、new_child()メソッドを使えば、既存のChainMapに新しい辞書を追加できます。たとえば、サンドイッチ職人がテストメニューで新作を試作し、そのうち2品を正式なメニューに加えたいとしましょう。次のコードでこの目的を達成できます。

test_menu = { "Veggie Deluxe": "$3.00", "House Club Special": "$3.65" }
new_menu = menu.new_child(test_menu)
print(new_menu)

実行すると、新しいサンドイッチ2品が先頭に追加された、更新済みのChainMapが返されます。

ChainMap({'Veggie Deluxe': '$3.00', 'House Club Special': '$3.65'}, {'BLT': '$3.05', 'Roast Beef': '$3.55', 'Cheese': '$2.85', 'Shrimp': '$3.55', 'Ham': '$2.85'}, {'Steak': '$3.60', 'Tuna Special': '$3.20', 'Turkey Club': '$3.20'})

まとめ

Pythonのcollectionsモジュールを活用すれば、組み込みコレクションの機能を拡張し、カスタムデータ構造のメソッドへアクセスできるようになります。リストやタプルといったコレクション型を扱いながら、素のPython(バニラPython)には備わっていない特定の機能が必要になったときに、このモジュールは非常に心強い味方となるでしょう。

本ガイドでは、具体的なコード例を交えながらPythonにおけるコレクションの基本を整理し、collectionsライブラリが提供する主要な4つの機能——CounternamedtupledefaultdictChainMap——の使い方を詳しく解説しました。

これであなたも、Python collectionsモジュールをプロのように使いこなすための基礎知識を身につけました。ぜひ実際のコードで試してみてください!

  1. Pythonインタープリターとは?仕組みと初心者向けオンライン環境を徹底解説

    Pythonは学びやすいプログラミング言語として知られています。その理由のひとつが、自分のマシンに正しいバージョンのPythonをインストールしなくても、オンラインで利用できるPythonインタープリターが数多く存在する点です。本記事では、Pythonインタープリターの仕組みについて解説し、初心者にも使いやすい人気のオンラインインタープリターをご紹介します。 Pythonプログラムはどのように実行されるのか? PythonはJavaと同様に、純粋なインタプリタ言語ともコンパイラ言語とも分類できず、両方の性質を併せ持っています。 ここでいう「コンパイル」とは、特定のプラットフォームに依存し

  2. Pythonでファイル名を変更する方法:os.rename()の基本と実践例

    Pythonのos.rename()メソッドは、ファイルの名前を変更するための機能です。このメソッドは「変更前のファイルパス」と「変更後のファイルパス」という2つの引数を受け取ります。新しいファイルパスには、元とは異なるファイル名を指定する必要があります。 Pythonでファイルを扱っていると、特定のファイルの名前を変更したくなることがあります。たとえば、raw_data.csvというファイルがあった場合、プログラムの実行時にこれをold_data.csvにリネームしたいケースなどが考えられます。 そんなときに役立つのが、os.rename()メソッドです。このメソッドを使えば、Pyt