Address
304 North Cardinal St.
Dorchester Center, MA 02124

Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM

Pythonのタプルとcollectionsモジュール

Pythonのタプルをもっと便利にできるcollectionsモジュールのnamedtuple関数の紹介

Pythonのcollectionsモジュールのnamedtupleを使ってタプルをもっと便利にする方法の説明

今回はPythonのタプル(tuple)をより便利に使えるようにするcollectionsモジュールの中の機能、namedtupleの紹介です。

タプルの不便なところ

Pythonのタプルは例えば次のように作成できます。

new_tuple = ('Tom', 'USA)

そしてインデックス(何番目かという情報)を使って次のように使えます。標準ではインデックスは「0番」から始まります。

print(new_tuple[0])  

結果は「Tom」と表示されます。

このようにタプルはインデックスを指定することでしかその情報にアクセスできません。

今回のようにタプルの要素が2つしかなければ、それでもいいのですが、要素が10個とかになってくると、「インデックスの8番目って何の情報だったかな?」とわからなくなります。

この点、辞書の場合だとキーワードを使ってその情報にアクセスできます。たとえば、

new_dic = {'Name':'Tom', 'Country':'USA'} 

という辞書を作ると、

  • Countryという要素があること
  • USAとはアメリカという国名の略記であること

という情報がわかりやすくなります。

これはコードの可読性・理解を向上させます。

普通のタプルだとその中身が多くなるとこのような可読性が損なわれてしまうのですね。そういった不便がタプルにはあります。

そこで、通常のタプルをもう少し使いやすくする、タプルを拡張させるような機能がPythonには標準で用意されています。それが、collectionsモジュールの中にあるnamedtupleという関数です。

collectionsモジュールのnamedtuple関数を使ってタプルを便利にする方法

collectionsモジュールとは何か?

Pythonに標準で用意されているcollectionsモジュールとは、Pythonの公式ドキュメント(collections — コンテナデータ型)によると、

このモジュールは、汎用の Python 組み込みコンテナ dict, list, set, および tuple に代わる、特殊なコンテナデータ型を実装しています。

と記載されています。大雑把にいうと、標準の辞書、リスト、セット、タプルといったものの機能を拡張して便利に使えるようにするモジュールという意味です。

そしてそのcollectionsモジュールには、次のような機能が含まれています。

namedtuple()名前付きフィールドを持つタプルのサブクラスを作成するファクトリ関数
deque両端における append や pop を高速に行えるリスト風のコンテナ
ChainMap複数のマッピングの一つのビューを作成する辞書風のクラス
Counterハッシュ可能なオブジェクトを数え上げる辞書のサブクラス
OrderedDict項目が追加された順序を記憶する辞書のサブクラス
defaultdictファクトリ関数を呼び出して存在しない値を供給する辞書のサブクラス
UserDict辞書のサブクラス化を簡単にする辞書オブジェクトのラッパ
UserListリストのサブクラス化を簡単にするリストオブジェクトのラッパ
UserString文字列のサブクラス化を簡単にする文字列オブジェクトのラッパ
Pythonの公式ドキュメント(collections — コンテナデータ型)より

今回はこのうち、一番上のnamedtuple()関数の紹介です。

namedtuple()関数とは何か?

namedtuple関数については、上記公式ドキュメントでは次のように説明されています。

ypename という名前の tuple の新しいサブクラスを返します。新しいサブクラスは、 tuple に似ているけれどもインデックスやイテレータだけでなく属性名によるアクセスもできるオブジェクトを作るのに使います。このサブクラスのインスタンスは、わかりやすい docstring (型名と属性名が入っています) や、 tuple の内容を name=value という形のリストで返す使いやすい __repr__() も持っています。

Pythonの公式ドキュメント(collections — コンテナデータ型)より

ポイントは「tupleに似ているけれども」という点、そして「属性名によるアクセスもできるオブジェクト」を作ることができるという点です。

まるでクラスのようですね。

もちろんクラスそのものではないのですが、個人的には乱暴な説明ですが「タプルのクラス化」あるいは「クラスっぽいタプルオブジェクトを作る」というイメージを最初に持つとわかりやすいと思います。

namedtuple()の使い方

collectionsモジュールのnamedtuple()をさっそく使ってみましょう。

まずcollectionsモジュールの内部にあるので、次のようにインポート文によってインポートします。

from collections import namedtuple

そして次のように使います。

LawsonShop = namedtuple('Lawson', 'store_code, address, store_type')

まず右辺ですが、これは、namedtuple関数によって、

  • 作成されるオブジェクトの名前がLawson
  • Lawsonの中身は、store_code(店コード)、address(所在地)、store_type(店の種類:直営かフランチャイズか)

という情報を持つサブクラスを作るという意味です。

注意していただきたいのが、右辺の中の、

'store_code, address, store_type'

の書き方です。上のものはコンマで区切っていますが、

'store_code address store_type'

このように半角スペース1つで区切って書くことも可能です。

しかし、

'store_code', 'address', 'store_type'

このように、引用符でそれぞれの単語を区切るというリストを作るときのような書き方はできません。なぜかというと、この部分は、実は「文字列.split()」が呼ばれてそれが実行されているからです。ここでいう文字列は全体tとして1つの文字列ですので、複数の文字列となる書き方は不適切となります。

そして、できあがったサブクラス(つまりクラス)を左辺のLawsonShopの代入しています。よってLawsonShopもサブクラスであって、クラスの一種です。

左辺と右辺のオブジェクトが同一なのかどうか調べてみましょう。

id(Lawson)
id(LawsonShop)

これでそれぞれのオブジェクトIDを確認すると異なり、左辺と右辺はそれぞれ別のオブジェクトだとわかります。

では、左辺のサブクラスLawsonShopを使って、インスタンスオブジェクトを作ってみましょう。

tokyo_shop = LawsonShop('12', 'Tokyo', 'franchisee')

tokyo_shopというインスタンスオブジェクトを作成しました。店コードは12、所在地は東京、店の種類はフランチャイズです。

こうしてできあがったオブジェクトのtokyo_shopはあくまでタプルとしての性質を有します。それゆえインデクスで情報の取得が可能です。

tokyo_shop[0]
tokyo_shop[1]
tokyo_shop[2]

それぞれ、12、Tokyo、franchiseeとなります。

上述のように辞書と異なり普通のタプルはインデックス番号ではないキーワードでのアクセスは不可能でしたが、このnamedtuple()によって作られたオブジェクトはまるで辞書のようにキーワードを使ってアクセスすることができます。

ただし辞書の使い方とはやや異なり、「クラスによって作られたインスタンスオブジェクト」っぽい使い方となります。次のコードを見てください。

tokyo_shop.store_code
tokyo_shop.address
tokyo_shop.store_type

これを実行すると、順番に12、Tokyo、franchiseeとなります。

またタプルは、「*」演算子によってアンパック(展開)することが可能です。

print(*shop)

こうすると、「12 Tokyo franchisee」と表示されます。

ただし、今回作ったtokyo_shopというオブジェクトはあくまでタプルとしての性質を持ちます。そしてタプルはイミュータブルです。つまり一度設定した値は後から代入で変更はできません。実際、たとえばstore_codeの初期設定12を22へ変えようとして、

tokyo_shop.store_code = '22'  # Errorがでます

このように直接的に代入してしまうとエラーが出ます。

collections.namedtuple()のまとめ

以上、collectionsモジュールのnamedtuple()関数について説明しました。まだ説明していない特徴も多少ありますが、今回の範囲で簡単にまとめておきますと、

  • import文を使ってインポートする
  • namedtuple()で作られたオブジェクトは、辞書っぽいキーワードでのアクセスが可能となり、コードがわかりやすくなる
  • しかし辞書のように使うのではなく、クラスから作られたインスタンスオブジェクトのように「オブジェクト名.属性名」という形式で使う
  • あくまでタプルなのでイミュータブルなまま

ということです。

プログラミングを学びIT業界へ転職するなら現役エンジニアから学べるプログラミングスクールTechAcademy [テックアカデミー]でオンライン講座を受講するのが良いと思います。1人で悩みながら学習を進めるよりもわかりやすく、費やす時間も少なく合理的・効率的に学習できるからです。

など各種の講座が用意されています。無料で体験できるテックアカデミー無料体験も用意されています。