namedtuple
がない¶
namedtuple
というのは名前付きのタプルです。
なくてもなんとかなるものの、あると地味に便利な機能の一つです。
Python にはタプルというデータ構造があり、任意個の値の組を一つの値として 扱うことができます。
例えば、時刻を数値の組で表すとこんな感じになると思います。
>>> dt = (2012, 12, 25, 23, 59, 59)
(これは2012年12月25日23時59分59秒を表しているつもりです)
この値から年や分などの個別の値を取り出そうとすると、タプルの中の位置を指定して 以下のように書くことになります (注: 位置は 0 から数えます)。
>>> year = dt[0]
>>> minute = dt[4]
これの問題点は、何番目に何の値が入っているかをいちいち数えないと このコードが正しいかどうかわからないということです。 以下のコードは間違っていますが、すぐに気がつきますか?
>>> minute = dt[5]
namedtuple
を使うと、位置に加えて属性名でも参照することができます。
>>> from collections import namedtuple
>>> DateTime = namedtuple('DateTime', 'year month day hour minute second')
>>> dt = DateTime(2012, 12, 25, 23, 59, 59)
>>> dt[0]
2012
>>> dt.year
2012
>>> dt.minute
59
名前で参照する方が圧倒的に分かりやすいですね。
Python 2.6 から namedtuple
が追加され、標準ライブラリのいくつかのモジュールで、これまでタプルを返していた関数が namedtuple
を返すように変更されました。
代表例は URL を要素に分解して一部を取り出す際に使う urlsplit()
関数です。
>>> from urlparse import urlsplit
>>> o = urlsplit('http://www.example.com:80/index.cgi?cmd=read#top')
>>> o
SplitResult(scheme='http', netloc='www.example.com:80', path='/index.cgi', query='cmd=read', fragment='top')
>>> o.path
'/index.cgi'
タプルとしてもアクセスできるので、従来のコードとも互換性があります。
>>> scheme, netloc, path, query, fragment = o
Python 2.4 ではこの書き方しかできません。
以下、主にプログラマ向けの注釈です。
実際には上記の例にあるような DateTime 型を定義する必要はなく、
datetime
クラスの timetuple()
メソッドが返す
time.struct_time
クラスを使うことができます。
>>> import datetime
>>> dt = datetime.datetime(2012, 12, 25, 23, 59, 59).timetuple()
>>> dt
time.struct_time(tm_year=2012, tm_mon=12, tm_mday=25, tm_hour=23, tm_min=59, tm_sec=59, tm_wday=1, tm_yday=360, tm_isdst=-1)
余談ですが、この time.struct_time
型は namedtuple
かと思ったら違いました。
>>> isinstance(dt, tuple)
False
>>> dt.__class__.mro()
[<type 'time.struct_time'>, <type 'object'>]
比較のため、 urlsplit
の戻り値の型を調べてみると、
tuple
のサブクラスのインスタンスであることが分かります。
>>> from urlparse import urlsplit
>>> o = urlsplit('http://www.example.com:80/index.cgi?cmd=read#top')
>>> isinstance(o, tuple)
True
>>> o.__class__.mro()
[<class 'urlparse.SplitResult'>, <class 'urlparse.SplitResult'>, <type 'tuple'>, <class 'urlparse.ResultMixin'>, <type 'object'>]
time
が C 拡張モジュールなので、そのせいかとも思うのですが、
詳細は分かりません。