What's New in Python 2.1
************************

著者:
   A.M. Kuchling


はじめに
========

この記事はPython 2.1の新機能について説明します。Python 2.1には Python
2.0ほど多くの変更点はありませんが、楽しい驚きがあります。2.1はPythonの
拡張計画（PEP）を使い動かす最初のリリースであり、大きい変更点のほとん
どは、より詳細なドキュメントや変更のための設計原理を提供するPEPに付随
しています。この記事は新機能について網羅していませんが、Pythonプログラ
マのための新機能について概要を示します。特に興味のある任意の新機能の詳
細については、Python 2.1ドキュメントか特定のPEPを参照してください。

Python開発チームの最近の目標の一つとして新しいリリースのペースを上げて
おり、一つのリリースにつき6～9ヶ月ごとにリリースしています。2.1はこの
速いペースになって出てきた最初のリリースで、初のアルファ版は、2.0の最
終版がリリースされた3ヶ月後の1月に登場しました。

Python 2.1の最終版は2001年4月17日に作成されました。


PEP 227: 入れ子状のスコープ
===========================

Python2.1における最も大きな変更点はPythonのスコープルールです。
Python2.0では、ある指定された時点である変数の名前を検索するために多く
ても3つの名前空間、つまりローカル、モジュールレベル、ビルトイン名前空
間しか使われませんでした。このことは直感的な期待と一致せずしばしば人々
を驚かせました。例えば、入れ子になった再帰関数の定義は動きません:

   def f():
       ...
       def g(value):
           ...
           return g(value-1) + 1
       ...

名前 "g" はローカルの名前空間にもモジュールレベルの名前空間にも紐付か
ないので、関数 "g()" は常に "NameError" 例外を上げます。これは実際には
大した問題ではありません (このような内部関数を再帰的に定義する頻度はそ
う多くありません)が、 "lambda" 式をより使いにくくするのでこれについて
は問題です。 "lambda" を使うコードにおいて、デフォルトの引数としてこれ
らを渡してコピーされるローカル変数を頻繁に見かけます。:

   def find(self, name):
       "Return list of any entries equal to 'name'"
       L = filter(lambda x, name=name: x == name,
                  self.list_attribute)
       return L

過度な関数型スタイルで書かれた Python コードの可読性は、結果的にはひど
く苦痛を感じるものですね。

Python 2.1の最も重要な変更点は、この問題を解決するために静的なスコープ
が追加されたことです。最初の効果として、"name=name" という例ではデフォ
ルトの引数は必要ありません。簡単に言えば、指定された引数名が関数内の値
に割り当てられない場合("def"、"class" または "import" ステートメントの
割り当てによって)、変数の参照は外側のスコープのローカル名前空間で検索
されます。ルールや実装の詳細はPEPで参照できます。

この変更は、同じ変数名がモジュールレベルと関数の定義が含まれている関数
内のローカルの両方で変数名として使用されているコードで、互換性の問題を
引き起こす可能性があります。ですがむしろ気にしなくてよいでしょう。その
ようなコードはそもそも最初から相当こんがらかっているので。

この変更の副作用の一つは、 "from module import *" と "exec" の両ステー
トメントが特定の条件下の関数スコープ内で不正となることです。 Python の
リファレンスマニュアルははじめからずっと "from module import *" はトッ
プレベルモジュールでのみ合法であると言ってきましたが、以前の CPython
インタプリタはこれを一度も強制していませんでした。入れ子になったスコー
プ実装の一環として、Python のソースをバイトコードに変換するコンパイラ
は、内包されたスコープ内の変数にアクセスするために別のコードを生成する
必要があります。 "from module import *", "exec" はコンパイラにこれを理
解することを不可能にしてしまいます。なぜならそれらはコンパイル時にはわ
からないローカル名前空間に名前を追加するからです。それゆえ、もし関数が
関数定義を含んだり自由な変数に "lambda" の語句を含んだりする場合、コン
パイラは "SyntaxError" 例外を上げて知らせます。

前述した説明を少し明確にするため、例を挙げます:

   x = 1
   def f():
       # The next line is a syntax error
       exec 'x=2'
       def g():
           return x

"exec" 文を含む 4 行目は文法エラーです。 "exec" としては新しいローカル
変数 "x" を定義したいのですが、これは "g()" からアクセスされなければな
りません。

これは実際には大した制約でもないはずです。 "exec" が Python コードで使
われるのは稀です(使われているとしたら大抵どこか貧弱な設計であることの
証)。

互換性の問題が考慮されて、入れ子のスコープは段階的導入につながりました
; Python 2.1 ではそれらはデフォルトで有効になっていませんが、 **PEP
236** に記載されているように、future 文を使用してモジュール内でオンに
することができます。(**PEP 236** の更なる議論について、続くセクション
を参照してください。) Python 2.2では入れ子になったスコープがデフォルト
になり、それをオフにする方法はありませんが、ユーザは 2.1 の全ライフタ
イムを通して、導入の結果起きるあらゆる破損を修正し続けるでしょう。

参考:

  **PEP 227** - 静的に入れ子になったスコープ
     Jeremy Hylton著、実装


PEP 236: __future__ 指示文
==========================

ネストされたスコープへのこの対応は、リリース 2.1 ではコードを壊すこと
の危険性について広く懸念されており、  Pythoneer 達に保守的なアプローチ
を選ばせるには十分でした。このアプローチは、必須とするリリース N+1 に
対する、 リリース N でのオプション機能として有効化という序奏、というも
のです。

この構文は "__future__" という名の予約モジュールを使う "from...import"
ステートメントを使用します。ネストしたスコープは以下のステートメントで
有効にできます。

   from __future__ import nested_scopes

普通 の "import" ステートメントに見えますが、実は違います; このような
未来のステートメントが置かれる場所には厳格なルールがあります。これらは
モジュールの冒頭にしか置けませんし、必ず何らかのPythonコードや正規の
"import" ステートメントの前になければなりません。それと言うのもこのよ
うなステートメントは、Pythonのバイトコードコンパイラがコードを解析し、
バイトコードを生成する方法に影響しますので、生成されるバイトコードとな
るステートメントの前になくてはならないのです。

参考:

  **PEP 236** - バック・トゥ・ザ・ "__future__"
     Tim Peter著、Jeremy Hylton主実装


PEP 207: 拡張比較
=================

以前のバージョンでは、ユーザ定義クラスや拡張型の比較を実装するための
Python のサポートはとても単純なものでした。クラスは 2 つのインスタンス
を与えられる "__cmp__()" メソッドを実装でき、実際の値がどうあれ、同値
の場合には 0 、そうでないなら +1 か -1 を返せるだけでした; メソッドは
例外を上げることも、ブール値以外のものを返すこともできませんでした。
Numeric Python が使われるような複雑な計算プログラムでは、要素ごとに与
えられた比較結果を含む行列を返し、2 つの行列を要素単位で比較できること
がより便利なので、Numeric Python のユーザはこのモデルがとても脆弱で限
定的であることにしばしば気付きました。もし 2 つの行列サイズが異なる場
合、この比較はエラー通知の例外を上げられなければなりません。

Python2.1で、このニーズを満たすために拡張比較が追加されました。Python
のクラスは、"<"、"<="、">"、">="、"=="、"!=" の各演算を個別にオーバー
ロードできます。この新しい特殊メソッドの名前は:

+-------------+------------------+
| 演算        | メソッド名       |
|=============|==================|
| "<"         | "__lt__()"       |
+-------------+------------------+
| "<="        | "__le__()"       |
+-------------+------------------+
| ">"         | "__gt__()"       |
+-------------+------------------+
| ">="        | "__ge__()"       |
+-------------+------------------+
| "=="        | "__eq__()"       |
+-------------+------------------+
| "!="        | "__ne__()"       |
+-------------+------------------+

(特殊メソッドはFortranの ".LT." や ".LE." 等々の演算子にちなんで命名さ
れています。プログラマはほぼ確実にこれらの名前を熟知していますので、覚
えやすいでしょう。)

これらの特殊メソッドは "method(self, other)" の形式になっており、
"self" が演算子の左辺、"other" が右辺のオブジェクトになります。例えば
、式 "A < B" は "A.__lt__(B)" を呼び出します。

これらの特殊メソッドは何でも、つまり真偽値や行列、リストや他のPython
オブジェクトを返せます。もし比較が不可能であったり、矛盾していたり、意
味がない場合は、代わりに例外を上げることができます。

ビルトインの "cmp(A,B)()" 関数は拡張比較機構を利用出来、使用する比較演
算を指定する省略可能引数を受け付けるようになっています。指定には文字列
""<"", ""<="", "">"", "">="", ""=="", or ""!="" のいずれか一つを渡しま
す。省略可能のその 3 番目引数が省略されて呼ばれれば、 "cmp()" は以前の
バージョンの Python のように -1, 0, または +1 だけを返します; 指定され
れば、それはその適切なメソッドを呼び出し、任意の Python オブジェクトを
返せます。(訳注: 2015年の今となって、ここに書かれている cmp の仕様が実
在したのか不明な状態になっている。ビルトインの cmp リファレンスにはこ
れに関係する履歴は書かれていない。What's New を 2.7 まで追いかけても以
後変更された記録はない。)

C プログラマにとって興味深い関連する変更があります。型オブジェクトに新
しい "tp_richcmp" スロットと、この拡張された比較を行うAPIが追加されま
した。ここではC APIについて言及しませんが、あながた関連する関数のリス
トを見たければ、 **PEP 207** かバージョン2.1のC APIドキュメントを参照
してください。

参考:

  **PEP 207**: 拡張比較
     David Ascher によるかつての仕事に大きく拠りますが  Guido van
     Rossum によって著され、実装されました。


PEP 230: 警告フレームワーク
===========================

10 年の間に、Python は途中で廃止されたモジュールと機能の特定の番号を蓄
積してきました。どれだけのコードが活用されているか知る術はないので、機
能を削除して問題ないか把握することは困難です。その機能に依存するプログ
ラムは一つもないかもしれませんし、たくさんあるかもしれません。より構造
化された方法で古い機能を削除できるようにするために、警告のフレームワー
クが追加されました。Python の開発者がある機能を取り除きたいときは、ま
ずは Python の次のバージョンで警告を引き起こします。続く Python バージ
ョンで開発者はその機能を削除出来、ユーザは古い機能の使用を取り除くため
に Python リリースサイクル一つ丸々使えます。

Python 2.1 はこのスキームで使われる警告フレームワークを追加します。ま
た、警告の表示機能や表示させたくない警告を除外する機能を提供する、
"warnings" モジュールを追加します。サードパーティーのモジュールはまた
、彼らがサポート対象外にしたい古い機能を非推奨と知らしめるのにこのフレ
ームワークを利用できます。

例えば、Python2.1では "regex" モジュールは廃止されたので、これをインポ
ートすると警告が表示されます:

   >>> import regex
   __main__:1: DeprecationWarning: the regex module
            is deprecated; please use the re module
   >>>

警告は "warnings.warn()" 関数を呼び出すことで発行できます:

   warnings.warn("feature X no longer supported")

最初のパラメータは警告メッセージです。任意追加のパラメータは、特定の警
告カテゴリを指定するために利用することができます。

特定の警告を無効にするためにフィルターを追加できます。また警告を抑止す
るためにメッセージまたはモジュール名に正規表現が適用できます。例えば
"regex" モジュールを使ったプログラムで、今すぐには "re" モジュールに変
換する時間をかけられないプログラムがあるとします。警告は以下呼び出しに
より抑制できます:

   import warnings
   warnings.filterwarnings(action = 'ignore',
                           message='.*regex module is deprecated',
                           category=DeprecationWarning,
                           module = '__main__')

これは "__main__" モジュール内で引き起こされた "DeprecationWarning" 警
告だけに適用され、 "regex" モジュールが非推奨となったことについてのメ
ッセージにマッチする正規表現を適用するフィルタを追加し、そして結果とし
てそのような警告は無視されることになります。警告を一回きりの表示にした
り、違反コードが実行されるたびに表示したり、警告ではなく例外に切り替え
てプログラム停止することも出来ます(例外が普通の方法で捕捉されない限り
、です、もちろん)。

関数は、警告を発行するための Python の C API にも追加されました。詳細
については PEP 230 または Python の API ドキュメントを参照してください
。

参考:

  **PEP 5** - 言語の進化のためのガイドライン
     Python から古い機能を削除する時に従うべき手順を示すため、 Paul
     Prescod により書かれました。当 PEP に記載された方針は正式に採用さ
     れていませんが、最終的な方針も Prescod の提案とおそらくさほど違い
     はないでしょう。

  **PEP 230** - 警告フレームワーク
     Guido van Rossum 著、実装


PEP 229: 新しいビルドシステム
=============================

Python のコンパイル時、ユーザはソースツリーの中に入って、様々な追加モ
ジュールを有効にするために "Modules/Setup" ファイルを編集しなければな
りませんでした; デフォルトのセットは比較的小さくて、ほとんどの Unix プ
ラットフォームで、コンパイルするモジュールを制限しています。これは、特
に Linux に顕著ですが、たくさんの追加機能を持った Unix プラットフォー
ムでは、Python インストレーションはしばしば、そう出来るのに有用なモジ
ュールを全く含まない、といったことが起こることを意味しています。

Python 2.0 は、配布と拡張のインストールをするためのモジュールのセット
である Distutils を追加しました。Python 2.1 では Distutils を、たくさ
んの拡張モジュールの標準ライブラリを、サポートする機器かどうかを自動検
出してコンパイルするのに使っています。これが Python インストレーション
をより簡単に、より機能的とするものであることが期待されています。

モジュールを有効化するために "Modules/Setup" を編集する必要性の代わり
に、Python ソースツリーのトップレベルディレクトリにある "setup.py" ス
クリプトがビルド時に実行され、システムのモジュールとヘッダファイルを調
べることによって、どのモジュールが有効に出来るのかを検出しようと試みま
す。モジュールが "Modules/Setup" 内でそう構成されていれば、 "setup.py"
スクリプトはそのモジュールをコンパイルしようとはせずに "Modules/Setup"
ファイル内容に従います。これは特定のプラットフォームで必要となるヘンチ
クリンなコマンドラインフラグやライブラリフラグを特定する手段も与えてく
れます。

もう一つの大きなビルド機構の変更点は Neil Schemenauer による再構成で、
今や Python は、トップディレクトリと "Python/", "Parser/", "Objects/",
"Modules/" サブディレクトリにあった別々の Makefile が再帰的にビルドす
る代わりに、再帰をしないトップレベルの単一 makefile を使うようになって
います。このことで Python のビルドは速くなり、 Makefile をもてあそぶの
が単純明快になっています。

参考:

  **PEP 229** - Distutils を使った Python のビルド
     A.M. Kuchling 著、実装


PEP 205: 弱参照
===============

"weakref" モジュールを通して利用出来る弱参照(weak references)は、ささ
やかですが有用な、Python プログラマの道具箱に新たに加わったデータ型で
す。

オブジェクトへの参照(辞書内やリスト内を思い浮かべてください)を記憶して
おくということは、オブジェクトを生き永らえさせるという副作用を持ってい
ます。少しばかりの、この振る舞いが望ましくない特殊なケースがあります。
オブジェクトのキャッシュがその最もありがちな一つで、もう一つはツリーの
ようなデータ構造での循環参照です。

例えば、他の関数 "f(x)" の結果を、その関数の引数と結果を辞書に格納する
ことでキャッシュするメモライジング関数を考えてみましょう。

   _cache = {}
   def memoize(x):
       if _cache.has_key(x):
           return _cache[x]

       retval = f(x)

       # Cache the returned object
       _cache[x] = retval

       return retval

このバージョンは整数のような単純なものにはうまく働きますが、副作用を持
っています; 辞書 "_cache" は戻り値への参照を保持するので、それらは
Python プロセスが終了してクリーンアップされない限り、解放されません。
整数であればそれは気にすることではありませんが、"f()" がオブジェクトや
何かメモリをたくさん使うようなデータ構造を返すならば、これは問題になる
かもしれません。

弱参照は、オブジェクトをその時間を超えて生き永らえさせたくないキャッシ
ュの実装のための手段を提供します。オブジェクトがアクセス出来るのが弱参
照からのみである場合、そのオブジェクトは解放されて、その弱参照は参照し
ているそのオブジェクトがもはや存在しないことを表明します。オブジェクト
*obj* への弱参照を作るには、 "wr = weakref.ref(obj)" とします。参照さ
れているオブジェクトは、それがあたかも関数であったかのように弱参照を「
コール」することで得ます: "wr()" 。それは参照されたオブジェクトを返す
か、もう存在していないのであれば "None" を返します。

これでオブジェクトを生き残らせないキャッシュを使う "memoize()" を、キ
ャッシュ内に弱参照を記憶するというやり方で書けます:

   _cache = {}
   def memoize(x):
       if _cache.has_key(x):
           obj = _cache[x]()
           # If weak reference object still exists,
           # return it
           if obj is not None: return obj

       retval = f(x)

       # Cache a weak reference
       _cache[x] = weakref.ref(retval)

       return retval

"weakref" モジュールでは、弱参照のように振舞うプロキシオブジェクトも作
れます --- プロキシオブジェクトによってのみ参照されるオブジェクトが解
放されます -- オブジェクトを取り出すために明示的に「呼び出す」必要をな
くすためにプロキシは、全てのオブジェクトへの操作を、オブジェクトが生き
ている限り透過的に転送します。オブジェクトが解放された場合、プロキシを
使おうとすると "weakref.ReferenceError" 例外が起こります:

   proxy = weakref.proxy(obj)
   proxy.attr   # Equivalent to obj.attr
   proxy.meth() # Equivalent to obj.meth()
   del obj
   proxy.attr   # raises weakref.ReferenceError

参考:

  **PEP 205** - 弱参照
     Fred L. Drake, Jr. 著、実装


PEP 232: 関数の属性
===================

Python 2.1 では、関数に任意の情報をアタッチさせる(付随させる)ことが出
来るようになりました。人々はしばしば関数やメソッドについての情報を保持
するのに docstring を使ってきました。というのも "__doc__" だけが唯一関
数に任意の情報をアタッチ出来る方法だったからです。例えば、Zope ウェブ
アプリケーションでは、関数は docstring に情報を持つことによって公開ア
クセスのために安全かどうかマークされ、John Aycock の SPARK 解析フレー
ムワークでは docstring は BNF 文法記述の部分を、解析のために保持してい
ました。この「詰め込み」は嘆かわしいことです。docstring はまったくもっ
て関数のドキュメンテーションを保持するのに意図されたものです。例えば
Zope では自分のために行儀よく関数にドキュメント付け出来ないということ
です。

ついに関数に、任意の属性をセットし、取り出すことが出来るようになりまし
た。普通の Python 構文で出来ます:

   def f(): pass

   f.publish = 1
   f.secure = 1
   f.grammar = "A ::= B (C D)*"

属性を含んだ辞書に、関数の属性 "__dict__" としてアクセス出来ます。クラ
スインスタンスの "__dict__" 属性とは違って、関数では実際には、
"__dict__" に別の辞書を代入出来ます。ですが、新しい値は普通の Python
辞書に制限されています; ズルは *出来ません* し、 "UserDict" インスタン
スやなにかほかのマッピングのように振舞うデタラメなオブジェクトはセット
出来ません。

参考:

  **PEP 232** - 関数の属性
     Barry Warsaw 著、実装


PEP 235: 大文字小文字を区別しないプラットフォームでのモジュールの読み込み
=========================================================================

いくつかのオペレーティングシステムは、大小文字区別に無関心なファイルシ
ステムを持っています。MacOS と Windows がその代表例です。それらシステ
ムにおいてはファイル名 "FILE.PY" と "file.py" の区別が出来ません。たと
えそれが元のファイル名を尊重して格納出来たとしてもです(それらは大小文
字維持、でもあります)。

Python 2.1 では "import" 文が、case-insensitive (大小文字に無関心)なプ
ラットフォームで case-sensitivity (大小文字への繊細さ)をシミュレートし
て動作します。Python は今や、まずはデフォルトで case-sensitive なマッ
チによる検索をし、それで見つからなければ "ImportError" を投げます。で
すから "import file" は "FILE.PY" をインポートしません。case-
insensitive マッチングは Python インタプリタ開始前に環境変数
"PYTHONCASEOK" をセットすることで要求出来ます。


PEP 217: 対話モード用 Display Hook
==================================

Python インタプリタを対話的に使う際には、コマンドの出力結果表示にはビ
ルトインの "repr()" 関数が使われます。Python 2.1 ではこの "repr()" の
代わりに呼び出される呼び出し可能オブジェクトを、 "sys.displayhook()"
変数にセット出来ます。たとえば特別な pretty- printing 関数をセット出来
ます:

   >>> # Create a recursive data structure
   ... L = [1,2,3]
   >>> L.append(L)
   >>> L # Show Python's default output
   [1, 2, 3, [...]]
   >>> # Use pprint.pprint() as the display function
   ... import sys, pprint
   >>> sys.displayhook = pprint.pprint
   >>> L
   [1, 2, 3,  <Recursion on list with id=135143996>]
   >>>

参考:

  **PEP 217** - Display Hook の対話的な使用
     Moshe Zadka 著、実装


PEP 208: 新しい型強制モデル
===========================

数値強制が C レベルでどのようになされるかについての修正は、とても大き
なものでした。これは Python の C 拡張の著者にのみ影響し、数値操作をサ
ポートする拡張型を書くのをより柔軟にするものです。

拡張型はその "PyTypeObject" 構造体に、新しい型強制モデルをサポートする
ことを示すために "Py_TPFLAGS_CHECKTYPES" フラグをセット出来るようにな
りました。そのような拡張型内では、数値的スロット関数は 2 つの引数が同
じ型であることを仮定しなくなります。代わりに、2 つの引数が異なる型を渡
せて、内部的に型変換を実行出来ます。スロット関数にそれが処理出来ない型
が渡された場合は、それが失敗であることを表すために "Py_NotImplemented"
シングルトン値への参照を返せます。この場合他の数値関数が試されて、おそ
らく操作を実行出来ます。それでも "Py_NotImplemented" を返すなら
"TypeError" が送出されます。Python で書かれた数値メソッドも
"Py_NotImplemented" を返せます。この場合インタプリタはメソッドが存在し
ないものとして振舞います。 (おそらく "TypeError" が投げられたり、オブ
ジェクトのほかの数値メソッドが試されます。)

参考:

  **PEP 208** - 型強制モデルの手直し
     Neil Schemenauer により著され、実装されましたが、大変多くを Marc-
     André Lemburg による以前の仕事に拠っています。C レベルで今では数
     値操作がどのように処理されるようになったかの細かい点を理解したけ
     れば、これを読んで下さい。


PEP 241: Pythonソフトウェアパッケージのためのメタデータ
=======================================================

Python ユーザーからのよくある苦情としては、存在するすべての Python モ
ジュールの一覧がないということです。T. Middleton's の
"www.vex.net/parnassus/" にあった Vaults of Parnassus (2009年2月に停止
、Internet Archive Wayback Machine <https://web.archive.org/web/20090
130140102/http://www.vex.net/parnassus/>`_ で閲覧可) が最大のものでし
たが、ソフトウェアの登録は任意だったため、多くの人は登録しませんでした
。

この問題をどうにかするための最初の小さな一歩として、Distutils の
**sdist** コマンドを使ってパッケージ化する Python ソフトウェアに "PKG-
INFO" と名付けられたファイルを含むようにしました。これには名前、バージ
ョン、著者 (カタログ化の用語ではメタデータ) のような情報を含んでいます
。 **PEP 241** が "PKG-INFO" ファイルに持てるフィールドの完全なリスト
を記述しています。Python 2.1 を使ったソフトウェアをパッケージ化し始め
た人々によってパッケージがどんどんメタデータを含み、自動的なカタログ化
システムを構築し、それを実験することが出来るようになります。その結果の
経験により、おそらく本当に良いカタログを設計出来、Python 2.2 でそのサ
ポートを構築出来るでしょう。例えば Distutils の **sdist** コマンドと
**bdist_*** コマンド群はあなたのパッケージをカタログサーバに自動的にア
ップロードする "upload" オプションをサポート出来るでしょう。

"PKG-INFO" を含んだパッケージの作成は Python 2.1 を使っていなくても開
始することが出来ます。Distutils の新しいリリースが以前のバージョンの
Python ユーザ向けにも作られているからです。Distutils のバージョン
1.0.2 が、多数のバグフィックスや拡張とともに、 **PEP 241** の変更を含
んでいます。これは https://www.python.org/community/sigs/current
/distutils-sig/ にある Distutils SIG から入手可能です。

参考:

  **PEP 241** - Pythonソフトウェアパッケージのためのメタデータ
     A.M. Kuchling 著、実装

  **PEP 243** - レポジトリアップロードモジュールのメカニズム
     Sean Reifschneider により著されました。このドラフト PEP は中央サ
     ーバに Python パッケージをアップロードする機構について提案してい
     ます。


新しいモジュールと改良されたモジュール
======================================

* Ka-Ping Yee が 2 つの新規モジュールを寄稿しました: "inspect" モジュ
  ールは、動作中の Python コードについての情報を取得するもので、
  "pydoc" モジュールは docstring を対話的に HTML またはテキストに変換
  します。オマケとして、 "Tools/scripts/pydoc" が自動的にインストール
  されるようになっていて、これは指定した Python モジュール、パッケージ
  、またはクラス名のドキュメントを "pydoc.py" を使って出力します。例え
  ば "pydoc xml.dom" はこのような出力をします:

     Python Library Documentation: package xml.dom in xml

     NAME
         xml.dom - W3C Document Object Model implementation for Python.

     FILE
         /usr/local/lib/python2.1/xml/dom/__init__.pyc

     DESCRIPTION
         The Python mapping of the Document Object Model is documented in the
         Python Library Reference in the section on the xml.dom package.

         This package contains the following modules:
           ...

  "pydoc" には TK ベースの対話的ヘルプブラウザも含まれています。
  "pydoc" はすぐに病みつきになります。お試しあれ。

* 2 つの異なる単体テスト用モジュールが標準ライブラリに追加されました。
  Tim Peters によって寄稿された "doctest" モジュールは、docstring 内に
  埋め込まれた実例を実行することによるテストのフレームワークで、期待の
  出力と結果を比較します。Steve Purcell の手による PyUnit は JUnit に
  触発された単体テストフレームワークです。JUnit も Kent Beck の
  Smalltalk のテストフレームワーク由来です。PyUnit についてのより詳細
  な情報は http://pyunit.sourceforge.net/ を参照してください。

* 新規の "difflib" モジュールは "SequenceMatcher" クラスを含んでおり、
  これは 2 つのシーケンスを比較し、一方のシーケンスから他方に変換する
  のに必要な変更点を計算します。例えば、このモジュールは Unix の
  **diff** プログラムに似たツールを書くのに使えます。事実、サンプルプ
  ログラム "Tools/scripts/ndiff.py" が、そのようなスクリプトをどのよう
  にして書くかを実演しています。

* "curses.panel" はパネルライブラリへのラッパーであり、ncurses と SYSV
  curses の一部であり、 Thomas Gellekum により寄稿されました。パネルラ
  イブラリは深さ(depth)の追加機能を持つウィンドウを提供しています。ウ
  ィンドウは深さ順での高い方、低い方に移動出来、パネルライブラリはパネ
  ルがどこで重なるか、区域のどちらが可視かを理解します。

* PyXML パッケージは Python 2.0 から少しのリリースでいなくなり、Python
  2.1 では "xml" パッケージの更新バージョンを含んでいます。いくつかの
  特筆すべき変更点には Expat 1.2 以降のバージョンのサポートがあり、
  Expat パーサで Python でサポートされる任意のエンコーディングのファイ
  ルを処理出来るようにし、SAX、DOM、 "minidom" モジュールについての色
  々なバグフィックスがあります。

* Ka-Ping Yee は未捕捉の例外を処理するもうひとつのフックも寄稿しました
  。 "sys.excepthook()" には呼び出し可能オブジェクトをセット出来ます。
  例外がどの "try"..."except" にも捕捉されない場合に、例外は
  "sys.excepthook()" に通されて、そこで好きなことを何でも出来ます。9
  回目の Python カンファレンスにおいて、Ping はこのフックを使ったアプ
  リケーションのデモを行いました。そこでは、スタックフレームを列挙する
  だけでなくそれぞれのフレームでの関数の引数とローカル変数の列挙も行う
  拡張トレースバックの表示をしていました。

* "asctime()" や "localtime()" のような "time" モジュールの多くの関数
  が、エポックからの秒数での浮動小数点数の引数を必要とします。これら関
  数の最も一般的な使い方は現在時刻とともに用いるものですから、浮動小数
  点数引数が省略可能となりました。値が与えられなければ現在時刻が使われ
  ます。例えばログファイルのエントリは普通現在時刻を含んだ文字列が必要
  なものですが、Python 2.1 では、以前では長々しい
  "time.asctime(time.localtime(time.time()))" と書かなければならなかっ
  たものを代わりに "time.asctime()" とすることが出来ます。

  この変更は Thomas Wouters により提案され、実装されました。

* "ftplib" モジュールがデフォルトでパッシブモードでファイルを取得する
  ようになりました。これはパッシブモードがファイアウォール配下ではより
  良く動作するようだからです。この要望は Debian のバグトラッキングシス
  テムから起こりました。ほかの Debian パッケージがファイル取得に
  "ftplib" を使い、ファイアウォールの元で動作しなかったのです。このこ
  とが誰かの問題になるとは思えません。Netscape のデフォルトがパッシブ
  モードですし、苦情を言う人々も稀でした。ですがもしもパッシブモードが
  あなたのアプリケーションやネットワーク構成にとって不適切である場合に
  は、FTP オブジェクトの "set_pasv(0)" を呼び出して、パッシブモードを
  無効にしてください。

* "socket" モジュールに、Grant Edwards により寄稿された、生のソケット
  へのアクセスのサポートが追加されました。

* "pstats" モジュールに、Python プログラムの時間計測プロファイルを表示
  する単純な対話的統計ブラウザが含まれるようになり、これはモジュールが
  スクリプトとして実行された場合に呼び出されます。Eric S. Raymond によ
  って寄稿されました。

* 実装依存の関数ですが "sys._getframe([depth])" が、現在の呼び出しスタ
  ックより、指定したフレームオブジェクトを返すものとして追加されました
  。 "sys._getframe()" は呼び出しスタックの一番上のフレームを返します
  。オプショナルな整数引数 *depth* を与えると、関数はスタックの一番上
  から下 *depth* ぶんの呼び出しのフレームを返します。例えば
  "sys._getframe(1)" は呼び出し元のフレームオブジェクトを返します。

  この関数は CPython のみに含まれ、 Jython や .NET 実装にはありません
  。デバッグのためだけに用い、製品コード内にこれを書いてしまう誘惑に打
  ち克ってください。


その他の変更と修正
==================

短めのリリースサイクルだったため Python 2.1 では比較的少ない変更でした
。CVS 変更ログの検索では 117 のパッチ適用と 136 のバグフィックスが見つ
かります。ともに少なく見積もっています。いくつかの注目に値する変更を紹
介します:

* 特殊化されたオブジェクトアロケータがオプショナルで利用可能になってい
  ます。これはシステムの "malloc()" よりも速くて省メモリであるはずです
  。このアロケータは C の "malloc()" 関数を大きなメモリプールを得るの
  に使い、それより小さなメモリ要求はこれらプールで実現しています。この
  機能は **configure** スクリプトに "--with-pymalloc" オプションを与え
  ることで有効化出来ます。実装の詳細については "Objects/obmalloc.c" を
  みてください。

  C 拡張モジュールの作者はこのオブジェクトアロケータを有効にしてテスト
  すべきです。というのもある種の誤ったコードが破壊されて、ランタイムに
  コアダンプを引き起こしうるからです。Python の C API 内には数多くのメ
  モリアロケーション関数がありますが、これは以前は単に C ライブラリの
  "malloc()" と "free()" への別名であり、何かの間違いでミスマッチな関
  数呼び出しをしても、誤りは気付かれないものでした。今回のこのオブジェ
  クトアロケータを有効化すると、これら関数は "malloc()" と "free()" へ
  の別名ではまったくなくて、メモリ解放に誤った関数を呼び出すとコアダン
  プし得ます。例えば "PyMem_New()" を使って獲得したメモリは "free()"
  ではなく "PyMem_Del()" を使って解放する必要があります。Python に含ま
  れるいくつかのモジュールがまさにこれに抵触し、修正の必要がありました
  。間違いなく多くのサードパーティモジュールが同じ問題を抱えているでし
  ょう。

  オブジェクトアロケータは Vladimir Marangozov により寄稿されました。

* 行指向のファイルI/Oの速度が改善されたのは、その速度が十分ではないこ
  とに不満を持つ人が多く、また、ナイーブなベンチマークとして使われるこ
  とが多かったからです。ファイルオブジェクトの "readline()" メソッドが
  高速に動作するよう書き換えられました。正確な値は、Cライブラリの
  "getc()" の遅さに依存するためプラットフォームごとに異なりますが、約
  66%高速になりました。特定のオペレーティングシステムではもっと速くな
  る可能性があります。 comp.lang.python での議論がきっかけとなり、Tim
  Peters がこの変更のためのベンチマークとコーディングの多くを行いまし
  た。

  また、 Jeff Epler によって、ファイルオブジェクトのための新しいモジュ
  ールとメソッドが追加されました。新しいメソッドの "xreadlines()" は、
  既存のビルトイン関数 "xrange()" に似ています。 "xreadlines()" は、逐
  次処理のみをサポートする不透明データ型のシーケンスオブジェクトを返し
  ます。これは、逐次的に行を読み込みますが、既存の "readlines()" メソ
  ッドのようにファイル全体をメモリに読み込むことはありません。以下のよ
  うに使用します。

     for line in sys.stdin.xreadlines():
         # ... do something for each line ...
         ...

  ライン I/O の変更についての詳しい説明は、
  https://mail.python.org/pipermail/python-dev/2001-January/ にある
  2001 年 1 月 1--15 日の python-dev のまとめをご覧ください。

* 辞書に新しくメソッド "popitem()" が追加されました。これで辞書の内容
  を破壊的にイテレートすることが出来ます。これは大きな辞書では速くなり
  えます。全てのキーまたは値を含んだリストを構築する必要がないからです
  。 "D.popitem()" は辞書 "D" からランダムに "(key, value)" ペアを削除
  して、その 2 要素タプルを返します。これは Moshe Zadka による示唆と事
  前のパッチののちに、Tim Peters と Guido van Rossum によりほとんどが
  実装されました。(---訳注: 速くなる理由の説明が、イテレータもジェネレ
  ータもなかった Python 2.1 時点での説明であることに注意してください。
  ---)

* "from module import *" を使ってインポートする際にインポートされる名
  前を制御出来るようになりました。インポートされるべき名前のリストを含
  む "__all__" 属性を定義することでこれを行えます。一つのよくある不平
  が、 "sys" や "string" のように、ほかのモジュールをモジュールがイン
  ポートする場合に、 "from module import *" がインポートしているモジュ
  ールの名前空間内にそれらを追加することです。これをフィックスするには
  、 "__all__" に公開名を単に列挙します:

     # List public names
     __all__ = ['Database', 'open']

  このパッチのより厳密な版が最初に示唆されて Ben Wolfson により実装さ
  れましたが、python-dev でのいくつかの議論を経てからより弱い最終版が
  チェックインされました。

* 文字列に "repr()" を適用するとこれまでは表示出来ない文字について、8
  進エスケープが使われていました。例えば改行コードは "'\012'" でした。
  これは Python の起源である C に追従した名残ですが、こんにちでは普段
  使いで 8 進エスケープが使われることは非常に少なくなりました。Ka-Ping
  Yee が 8 進の代わりに 16 進を使いつつ相応の文字には "\n", "\t", "\r"
  などのエスケープを使うよう示唆し、この新しい書式化を実装しました。

* コンパイル時点で検出される構文エラーがエラーとなったファイル名と行番
  号を含む例外を送出できるようになり、またこれによりコンパイラの再編成
  という喜ばしい副作用がありました。Jeremy Hylton により達成されました
  。

* 他のモジュールをインポートする C 拡張が "PyImport_ImportModule()" を
  使うように変更されました。これによりインストールされている任意のイン
  ポートフックが使われます。これは C コードより他のモジュールをインポ
  ートする必要があるサードパーティ拡張にも推奨されます。

* Unicode 文字データベースのサイズが Fredrik Lundh のおかげでさらに
  340K だけ小さくなりました。

* いくつかの新たなポートの寄与: MacOS X (by Steven Majewski), Cygwin
  (by Jason Tishler); RISCOS (by Dietmar Schwertberger); Unixware 7
  (by Billy G. Allie).

そしてよくあるマイナーなバグフィックス、マイナーなメモリリーク、ドキュ
メンテーション文字列の編集やほかの微調整があり、全てを列挙するには長過
ぎます。もし見たいのであれば、CVS ログで完全な詳細を読んで下さい。


謝辞
====

著者は提案の申し出や修正、様々なこの記事の草稿の助けをしてくれた以下の
人々に感謝します:  Graeme Cross, David Goodger, Jay Graves, Michael
Hudson, Marc-André Lemburg, Fredrik Lundh, Neil Schemenauer, Thomas
Wouters.
