namedtuple

標準の tuple は要素にアクセスするために数値インデックスを使用します。

bob = ('Bob', 30, 'male')
print 'Representation:', bob

jane = ('Jane', 29, 'female')
print '\nField by index:', jane[0]

print '\nFields by index:'
for p in [ bob, jane ]:
    print '%s is a %d year old %s' % p

tuples はシンプルな用途に便利なコンテナになります。

$ python collections_tuple.py
Representation: ('Bob', 30, 'male')

Field by index: Jane

Fields by index:
Bob is a 30 year old male
Jane is a 29 year old female

その一方で、それぞれの値に対応するインデックスがエラーを発生させることを覚えておいてください。特に tuple が大量のフィールドを持ち、その値が使用される場所から離れて構築される場合です。数値インデックスと同様に namedtuple はそれぞれの値に対応する名前を割り当てます。

定義

namedtuple インスタンスは、インスタンス毎にディクショナリを持たないので通常のタプルのようにメモリ効率が良いです。 namedtuple のそれぞれの種別はその独自クラスで表現され、 namedtuple() ファクトリ関数を使用して作成されます。その引数は新しいクラスの名前と要素の名前を含む文字列です。

import collections

Person = collections.namedtuple('Person', 'name age gender')

print 'Type of Person:', type(Person)

bob = Person(name='Bob', age=30, gender='male')
print '\nRepresentation:', bob

jane = Person(name='Jane', age=29, gender='female')
print '\nField by name:', jane.name

print '\nFields by index:'
for p in [ bob, jane ]:
    print '%s is a %d year old %s' % p
    

このサンプルは標準タプルの位置インデックスを使用するのと同様に、ドット表記(obj.attr)を使用する名前により namedtuple フィールドへアクセスできることを説明します。

$ python collections_namedtuple_person.py
Type of Person: <type 'type'>

Representation: Person(name='Bob', age=30, gender='male')

Field by name: Jane

Fields by index:
Bob is a 30 year old male
Jane is a 29 year old female

無効なフィールド名

フィールド名が解析されるときに無効な値だと ValueError 例外が発生します。

import collections

try:
    collections.namedtuple('Person', 'name class age gender')
except ValueError, err:
    print err

try:
    collections.namedtuple('Person', 'name age gender age')
except ValueError, err:
    print err
    

同じ名前を繰り返したときや Python のキーワードの名前は無効です。

$ python collections_namedtuple_bad_fields.py
Type names and field names cannot be a keyword: 'class'
Encountered duplicate field name: 'age'

namedtuple がプログラム制御外の値に基づいて作成される状況(例えば、前もってスキーマが分からないデータベースのクエリにより返される行を表示する)においては、そのフィールドの名前を変更する rename オプションに True をセットしてください。

import collections

with_class = collections.namedtuple('Person', 'name class age gender', rename=True)
print with_class._fields

two_ages = collections.namedtuple('Person', 'name age gender age', rename=True)
print two_ages._fields

class という名前のフィールドは _1 になり、重複した age フィールドは _3 に変更されます。

$ python collections_namedtuple_rename.py
('name', '_1', 'age', 'gender')
('name', 'age', 'gender', '_3')
Bookmark and Share