namedtupleについてのメモです。
概要
むかーしむかしにpython触っていた時(多分 2.0 とかそのへん)には、無かったのですが
最近またpython触るようになって、まず気に入ったのがこの namedtuple さん。
軽いし、フィールドアクセスできるし、なんといっても immutable なのがイイ。ついでにreprも用意してくれるのでデバッグ時に見やすい。
collectionsとitertoolsパッケージに用意されているものは、全部素晴らしいですね。(あと、functools.partialも) 数はそんなに多くないけど、ほんと便利なライブラリ。
なんですが、結構周りで知らない人もいたりしたので、使い方のメモ書きです。
サンプル
# --------------------------------------------------------------- # namedtupleは、「名前つきタプル」を作成する # 通常のタプルに、型名と名前つきのフィールドを付与出来るイメージ。 # 通常のタプルと同様に、イミュータブルであることは同じ。 # 値は、コンストラクト時に指定する。 # # フィールド名は、カンマ区切りの文字列で渡すか # シーケンスを指定する # --------------------------------------------------------------- Person = collections.namedtuple('Person', 'name,age') p = Person(name='test', age=30) pr('Person', p) try: p.name = 'test2' except AttributeError as e: pr('namedtupleはイミュータブル', e) # --------------------------------------------------------------- # フィールド名にはシーケンスを指定することも出来る # --------------------------------------------------------------- field_names = ('name', 'age') Person2 = collections.namedtuple('Person2', field_names=field_names) p2 = Person2(name='test2', age=30) pr('Person2', p2) # --------------------------------------------------------------- # 存在しないフィールド名を指定するとエラー # --------------------------------------------------------------- try: p3 = Person2(name='test3', age=33, hoge=10) except TypeError as e: pr('存在しないフィールド名を指定', e) # --------------------------------------------------------------- # verbose引数にTrueを指定するとクラス宣言を標準出力に出してくれる # (*) Python ドキュメントをみると、この指定は deprecated 扱い。 # 現在は、_source フィールドから取得するべきとのこと。 # --------------------------------------------------------------- collections.namedtuple('Person3', 'name', verbose=True) # ------------------------------------------------------------ # namedtuple は、通常のtupleと同様に利用できる。 # さらに、以下の3つのメソッドを持つ。 # ・_make # ・_asdict # ・_replace # また、以下のプロパティも持つ # ・_fields # ------------------------------------------------------------ MyVal01 = cols.namedtuple('MyVal01', ['name', 'value']) obj1 = MyVal01('hello world', 'value01') pr('obj', obj1) # namedtuple は、__dict__ を持たない try: pr('__dict__', obj1.__dict__) except AttributeError as e: pr('__dict__', e) # namedtuple は、__slots__ に 空タプルが設定される pr('__slots__', obj1.__slots__) # ------------------------------------------------------------ # _make メソッド # -------------------- # 既存のsequence, iterable から新しいオブジェクトを構築する。 # csvやデータベースなどの行からオブジェクトを作成するのに便利。 # ------------------------------------------------------------ rows = (['hello', 'value01'], ['world', 'value02']) for item in (MyVal01._make(row) for row in rows): pr('item', item) # ------------------------------------------------------------ # _asdict メソッド # -------------------- # フィールド名と値のOrderedDictを返す。 # 戻り値が OrderedDict なので、フィールドの並び順の通りに取得できる。 # (*) OrderedDictになったのは、python 3.1 から。 # ------------------------------------------------------------ obj_dict = obj1._asdict() pr('obj_dict', obj_dict) # 辞書から namedtuple を構築する場合は **kwargs 形式で渡す obj2 = MyVal01(**obj_dict) pr('obj2', obj2) pr('eq', obj1 == obj2) # ------------------------------------------------------------ # _replace メソッド # -------------------- # 指定したフィールドの値を置き換えた、新しい namedtuple を返す。 # namedtuple は、immutableなので、常に新しいオブジェクトを返す。 # ------------------------------------------------------------ obj3 = obj2._replace(name='world hello', value='value03') pr('obj3', obj3) pr('eq', obj3 == obj2) # ------------------------------------------------------------ # _fields プロパティ # -------------------- # 定義されているフィールド名をタプルで返す。 # ------------------------------------------------------------ pr('_fields', obj3._fields) # ------------------------------------------------------------ # namedtuple に、独自のメソッドを持たせる場合は # namedtuple を親クラスにしたクラスを新たに定義する。 # ------------------------------------------------------------ class MyVal02(cols.namedtuple('MyVal02', ['name'])): __slots__ = () @property def upper_name(self): return self.name.upper() obj4 = MyVal02('hello world 2') pr('obj4.name', obj4.name) pr('obj4.upper_name', obj4.upper_name)
ソースは以下でも見れます。
try-python/collections04.py at master · devlights/try-python · GitHub
try-python/collections07.py at master · devlights/try-python · GitHub
以下、参考にした情報です。
過去の記事については、以下のページからご参照下さい。
- いろいろ備忘録日記まとめ
サンプルコードは、以下の場所で公開しています。
- いろいろ備忘録日記サンプルソース置き場