【collections.namedtuple】Pythonでタプルに名前をつける方法

本記事は、collections.namedtupleの基本的な使い方を解説しています。引数やメソッドなどの特徴を説明するためのコード例を作成しています。それらを参考にしながらnamedtupleを使いこなせるようになりましょう。

本記事は、こちらのドキュメントを参考にしているため、pythonのバージョンによっては挙動が異なる場合があります。その場合は、ドキュメントを参照してください。

collectionsには、他にどんな関数があるのか気になる方は、こちらの記事にまとめています。

あわせて読みたい
【Python】collectionsでデータをよりスマートに管理しよう! データの管理は、プログラミングをする上でとても重要です。Pythonには、様々なデータを管理するためのモジュールが用意されています。これらのモジュールを使えば、よ...
目次

namedtupleとは

namedtupleは、Pythonのcollectionsモジュールに含まれるデータ型です。

この collections.namedtupleは次のような特徴があります。

  • タプルに名前を付けることができるので、タプルの中身がわかりやすくコードの可読性が上がる
  • namedtupleは、イミュータブルなデータ型なので、いつの間にか値を変更してしまっていたというような事故を防げる

今回は、このような特徴があるcollections.namedtupleの引数について具体的な使用例を交えて解説します。

また、collections.namedtupleの3つの追加メソッドと2つの属性についても見ていきます。

collections.namedtupleの引数

collections — namedtuple コンテナデータ型 — Python 3.11.0b5 ドキュメント

collections.namedtuple の引数の簡単な説明は以下になります。

  • typename: 生成するタプルの名前を文字列で指定します。
  • field_names: タプルに含めるフィールド名を文字列または文字列のイテレータで指定します。複数のフィールド名を指定する場合は、スペースで区切ります。
  • rename: フィールド名を小文字に変換して、同じフィールド名が複数ある場合に区別する場合は、True を指定します。デフォルトは False です。
  • defaults: 生成するタプルに初期値を指定するためのタプルを指定します。初期値を指定する場合は、フィールドの数と同じ数の値を指定する必要があります。
  • module: 生成するタプルを属するモジュールを文字列で指定します。デフォルトは None です。

では、それぞれ具体例を用いて使い方を見ていきましょう。

typename

typename引数は、生成するnamedtupleの型の名前を文字列で指定します。

typenameを指定することで、生成されるnamedtupleのインスタンスをよりわかりやすくすることができます。
・複数のnamedtupleを使用する場合、typenameを指定することで、どのnamedtupleのインスタンスであるかをわかりやすくすることができます。

以下は、typename引数を使用した例です。

from collections import namedtuple

# typename引数を使用する
Point = namedtuple('Point', ['x', 'y'])

# namedtupleを使用する
p = Point(x=1, y=2)
print(p)  # Output: Point(x=1, y=2)

field_names

field_names引数は、生成するnamedtupleに含めるフィールド名を文字列または文字列のイテレータで指定します。

ちなみに、後述のメソッド名や属性名がアンダースコア( _ )から始まるので、同じようにアンダースコアから始めるとValueError: Field names cannot start with an underscore: '_'というエラーがでます。

以下は、field_names引数を使用した例です。

from collections import namedtuple

# field_names引数を使用する
Person = namedtuple('Person', 'name')

# namedtupleを使用する
p = Person(name='John')
print(p)  # Output: Person(name='John')

複数のフィールド名を指定する場合は、以下のような記述方法があります。

from collections import namedtuple

# field_names引数を使用する
Person1 = namedtuple('Person1', ['name', 'age'])
Person2 = namedtuple('Person2', ('name', 'age'))
Person3 = namedtuple('Person3', ('name age'))
Person4 = namedtuple('Person3', ('name, age'))

# namedtupleを使用する
p1 = Person1(name='John', age=30)
p2 = Person2(name='John', age=30)
p3 = Person3(name='John', age=30)
p4 = Person4(name='John', age=30)
print(p1)  # Output: Person(name='John', age=30)
print(p2)  # Output: Person(name='John', age=30)
print(p3)  # Output: Person(name='John', age=30)
print(p4)  # Output: Person(name='John', age=30)

どの記述方法でも複数のフィールド名を指定できます。

複数のフィールド名を指定する方法
・リストにフィールド名を格納
・タプルにフィールド名を格納
・空白で区切る
・コンマで区切る

ちなみに、大文字と小文字は区別するので、異なるフィールド名として扱われます。

from collections import namedtuple

# namedtuple を作成
Person = namedtuple('Person', 'name Name', defaults=(0, 0))

# Person オブジェクトを作成
p = Person(name='Alice')
print(p)  # Person(name='Alice', Name=0)

rename

rename引数は、フィールド名を小文字に変換して、同じフィールド名が複数ある場合に区別する場合にTrueを指定します。デフォルトはFalseです。

rename=Trueの場合

以下は、rename=Trueの場合です。

from collections import namedtuple

# `rename=True` を指定して namedtuple を作成
Person = namedtuple('Person', 'name age age', defaults=(0, 0), rename=True)

# 名前と年齢が同じフィールドを持つ Person オブジェクトを作成
p = Person(name='Alice', age='30')
print(p)  # Person(name='Alice', age='30', _2=0)

上記の例では、ageがフィールドに二つあるので、二つ目のageが位置を示す_2に置き換わっています。

また、defのような予約語についても置き換えられます。

from collections import namedtuple

# `rename=True` を指定して namedtuple を作成
Person = namedtuple('Person', 'name age def', defaults=(0, 0), rename=True)

# Person オブジェクトを作成
p = Person(name='Alice', age='30')
print(p)  # Person(name='Alice', age='30', _2=0)

rename=Trueの場合
同じ名前のフィールド名や予約語と同じフィールド名などは、位置を示す文字に置き換えられる。

rename=Falseの場合

以下は、rename=Falseの場合、つまりデフォルトの場合に同じフィールド名を指定してみます。

from collections import namedtuple

# `rename=True` を指定して namedtuple を作成
Person = namedtuple('Person', 'name age age', defaults=(0, 0))

# 名前と年齢が同じフィールドを持つ Person オブジェクトを作成
p = Person(name='Alice')
print(p)  # ValueError: Encountered duplicate field name: 'age'

rename=Falseの場合
同じ名前のフィールド名や予約語と同じフィールド名を設定すると、エラーが出てしまう。

defaults

defaults: 生成するタプルに初期値を指定するためのタプルを指定します。

from collections import namedtuple

# フィールドに初期値を指定するように、タプルを定義します
Person = namedtuple('Person', 'name age height', defaults=(0, 0, 1))

# Person タプルを生成します
p = Person('Alice')

# Person タプルのフィールドにアクセスするには、属性名を使用します
print(p.name)    # Alice
print(p.age)     # 0 (初期値)
print(p.height)  # 1 (初期値)

上記の例では、defaults(0, 0, 1)と指定してageとheightの初期値を指定しています。

また、フィールドの数より一つ少なくしても初期値を設定できます。

from collections import namedtuple

# フィールドに初期値を指定するように、タプルを定義します
Person = namedtuple('Person', 'name age height', defaults=(1, 6))

# Person タプルを生成します
p = Person('Alice')

# Person タプルのフィールドにアクセスするには、属性名を使用します
print(p.name)    # Alice
print(p.age)     # 1 (初期値)
print(p.height)  # 6 (初期値)

この場合は、フィールドの始めに定義したnameにはdefaultsは考慮されず、次のageから初期値が入れられています。

もちろん、タプルを生成時にageやheightを設定すると、その設定が優先されます。

from collections import namedtuple

# フィールドに初期値を指定するように、タプルを定義します
Person = namedtuple('Person', 'name age height', defaults=(1, 6))

# Person タプルを生成します
p = Person('Alice', 22, 150)

# Person タプルのフィールドにアクセスするには、属性名を使用します
print(p.name)    # Alice
print(p.age)     # 22
print(p.height)  # 150

module

module: 生成するタプルを属するモジュールを文字列で指定します。デフォルトは None です。

from collections import namedtuple

# `module` 引数を指定して namedtuple を作成
Person = namedtuple('Person', 'name age gender', module='mymodule')

# Person オブジェクトを作成
p = Person(name='Alice', age='30', gender='female')
print(p)  # mymodule.Person(name='Alice', age='30', gender='female')
print(p.__module__) # mymodule

module 引数を指定すると、生成される名前付きタプルクラスの __module__ 属性が、指定された値に設定されます。

3つの追加メソッド

namedtupleには、以下のような3つの特殊メソッドがあります。

  • _make
  • _asdict
  • _replace

これらのメソッドを使うことで、namedtupleをより便利に操作することができます。

_make

_makeメソッドは、長さが同じであるタプルやイテラブルなオブジェクトから、同じ型のnamedtupleを作成することができます。

from collections import namedtuple

# namedtupleを使って、x座標とy座標を保持するPoint型を定義
Point = namedtuple('Point', ['x', 'y'])

# タプルを渡して、Point型のnamedtupleを作成
t = (1, 2)
p = Point._make(t)

# Point型のnamedtupleを表示
print(p)  # Point(x=1, y=2)

_asdict

_asdictメソッドは、namedtupleを辞書型に変換することができます。

from collections import namedtuple

# namedtupleを使って、x座標とy座標を保持するPoint型を定義
Point = namedtuple('Point', ['x', 'y'])

# Point型のnamedtupleを作成
p = Point(1, 2)

# namedtupleを辞書型に変換して表示
d = p._asdict()
print(d)  # {'x': 1, 'y': 2}

_replace

_replaceメソッドは、namedtupleのいくつかのフィールドを置き換えることができます。

from collections import namedtuple

# namedtupleを使って、x座標とy座標を保持するPoint型を定義
Point = namedtuple('Point', ['x', 'y'])

# Point型のnamedtupleを作成
p = Point(1, 2)

# x座標を置き換えて、新しいPoint型のnamedtupleを作成
p2 = p._replace(x=3)

# 新しいPoint型のnamedtupleを表示
print(p2)  # Point(x=3, y=2)

2つの属性

namedtupleには、以下の2つの特殊属性があります。

  • _fields
  • _field_defaults

_fields

namedtupleのフィールド名を保持するタプルを表示できます。

from collections import namedtuple

# namedtupleを使って、x座標とy座標を保持するPoint型を定義
Point = namedtuple('Point', ['x', 'y', 'z'], defaults=[0, 0, 0])

# _fields属性を使ってフィールド名を取得
print(Point._fields)  # ('x', 'y', 'z')

_field_defaults

namedtupleのフィールドに対するデフォルト値を保持する辞書型を表示できます。

from collections import namedtuple

# namedtupleを使って、x座標とy座標を保持するPoint型を定義
Point = namedtuple('Point', ['x', 'y', 'z'], defaults=[0, 0, 0])

# _field_defaults属性を使ってデフォルト値を取得
print(Point._field_defaults)  # {'x': 0, 'y': 0, 'z': 0}

まとめ

今回は、namedtupleの引数などを中心にまとめてみました。

pythonには便利なコンテナがあるということを頭の隅に置いておくことで、何かしらの時に役に立つかもしれません。そんな時に、この記事を思い出していただければ幸いです。

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!

コメント

コメントする

目次