Commits

Nozomu Kaneko committed cf66331

add docs

  • Participants
  • Parent commits f0a30eb

Comments (0)

Files changed (3)

 - set リテラルが使えない
 - :ref:`defaultdict`
 - :ref:`ordereddict`
-- namedtuple がない
+- :ref:`namedtuple`
+- os.path.relpath がない
 
 - xml.etree がない
-- json がない
+- :ref:`json`
 - argparse がない
 - functools がない
 - sqlite3 がない
+- multiprocessing がない
 - Python 2.4 で使えないライブラリ
 
   - webob >= 1.1 (ok: 1.0.8)
   - PyYAML >= 3.10 (ok: 3.09)
   - rsa >= 3.0 (ok: 1.3.3)
   - decorator >= 3.4.0 (ok: 3.3.3)
+  - simplejson >= 2.4.0 (ok: 2.3.3)
 
 - Exception が object のサブクラスではない
 - 相対インポートが使えない
+.. _json:
+
+:mod:`json` モジュールがない
+==============================
+
+JSON は JavaScript Object Notation の略ですが、
+最近では XML に代わる軽量データ記述言語として
+JavaScript に限らず様々な言語で用いられることが増えてきました。
+
+Python にも JSON を扱う標準ライブラリがありますが、これが追加されたのは
+Python 2.6 です。
+
+Python 2.4 では :mod:`simplejson` というサードパーティのライブラリを
+使うことが一般的です。
+サードパーティといっても Python 2.6 以降に含まれる :mod:`json` モジュールの
+元になったものなので、モジュール名以外の使い方は共通になっています。
+そのため、互換性を重視する場合は以下のような書き方をすることがあります。
+
+::
+
+  try:
+      import simplejson as json
+  except ImportError:
+      import json
+
+これによって、もし :mod:`simplejson` モジュールが存在したらそれを使い、
+ない場合に :mod:`json` モジュールが存在したら (つまり Python 2.6 以降なら)
+:mod:`json` モジュールを使う、ということが実現できます。
+
+注意点として :mod:`simplejson` の最新版は Python 2.4 をサポート
+していないため、インストールしようとするとエラーになります。
+公式に Python 2.4 をサポートしている最終バージョンは 2.0.9 ですが、
+2.3.3 までは Python 2.4 でも動作するようです。
+インストールする際はこれらの古いバージョンを指定してください。
+
+ちなみに、 JSON を扱うサードパーティのライブラリは :mod:`simplejson` 以外に
+
+- `cjson <http://pypi.python.org/pypi/python-cjson/>`_
+- `demjson <http://deron.meranda.us/python/demjson/>`_
+- `jsonlib <https://launchpad.net/jsonlib>`_
+- `jsonlib2 <http://code.google.com/p/jsonlib2/>`_
+
+等がありますが、
+`Python の JSONライブラリのパフォーマンステスト
+<http://www.ianlewis.org/jp/python-json-library-perf-test>`_
+によると、幸いなことにパフォーマンスを考慮しても :mod:`simplejson` を
+使えば良いそうです。
+.. _namedtuple:
+
+:class:`namedtuple` がない
+==============================
+
+:class:`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]
+
+:class:`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 から :class:`namedtuple` が追加され、標準ライブラリのいくつかのモジュールで、これまでタプルを返していた関数が :class:`namedtuple` を返すように変更されました。
+代表例は URL を要素に分解して一部を取り出す際に使う :func:`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 型を定義する必要はなく、
+:class:`datetime` クラスの :meth:`~datetime.timetuple` メソッドが返す
+:class:`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)
+
+余談ですが、この :class:`time.struct_time` 型は :class:`namedtuple` かと思ったら違いました。
+
+::
+
+  >>> isinstance(dt, tuple)
+  False
+  >>> dt.__class__.mro()
+  [<type 'time.struct_time'>, <type 'object'>]
+
+比較のため、 :class:`urlsplit` の戻り値の型を調べてみると、
+:class:`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'>]
+
+:mod:`time` が C 拡張モジュールなので、そのせいかとも思うのですが、
+詳細は分かりません。