2で書かれたスクリプトが動かなくなるような実装が行われた。後方互換性を崩してまで大きな仕様変更を行ったのか。それは、PythonがよりPythonらしくあるためだ。3が後方互換性を捨てても求めたもの」では、後方互換性を犠牲にしてでも、よりPythonらしくあるために仕様を変更したことに触れながら、いくつかの機能変更を見てきました。it)」というPythonの設計思想を、より高次元で実現するために必要だったからです。3.0で変更された仕様や新たに追加された機能を追いながら、Pythonという言語が目指す進化の方向性を探ってみましょう。2では、文字列型だけでなく、整数型にも2つの種類がありました。C言語のlong型に依存したint型です。1つは、メモリの許す限り大きな数値を扱えるlong型です。精度の低いint型がPythonに作られ、より大きな数値を扱いたいという要求からlong型が追加されました。int型とlong型をリテラルで書き分けられるように、数字の末尾に「L」を付けるというlong型のためのリテラルが用意されました。整数のための型が2種類あることも、古くからPythonの言語実装の一貫性を崩す仕様として議論されてきました。Pythonでは、仕様変更や機能追加に先だってPEPと呼ばれる技術文書が公開されます。237にint型とlong型を統合し、long型のみを整数型として採用するという提案がなされています。簡単そうに見える整数型の統合ですが、細かく見るといろいろな問題を引き起こす可能性をはらんでいます。PEPには、後方互換性に関する考察が書かれています。3.0では後方互換性を崩す仕様変更が許されました。そこで、2種類の整数型が統合され、long型相当の数値型に統一されました。237が提出されたのは2001年ですから、7年以上も統合が見送られていたことになります。2までは、int型同士の割り算は必ずint型を返していました。結果が小数点を含む数値となった場合は、内輪で一番近い整数を結果としていました。「1/2」の結果は「0」になります。3.0では、int型同士の割り算は必ずfloat型の数値を返します。従来通りint型を得たい場合には「//」という演算子を使います。数値型関連の機能追加では、ほかに2進数を扱う「0b1010」というリテラル表記が追加されています。notation」からとった「O(オー)」を使った「0o666」というリテラルに変更されています。16進数が「0xABCD」のような表記ですので、数値のリテラル表記も、拡張をしながら一貫性を持ったものに変更されていることが分かります。3.0では、これまでリストを返していたメソッドや組み込み関数がイテレータやview(ビュー)と呼ばれる軽量のイテレータ風オブジェクトを返すようになりました。関連した仕様変更でもっとも目立つのは、組み込み関数xrange()とrange()の統合かもしれません。xrange()もrange()も、for文などに添えて使い、順番に増減するシンプルな数値のリストを生成するために利用されます。2までのrange()はリストを生成します。このため、何十万回も繰り返し処理を行うような場合はメモリ効率が悪くなってしまいます。range()を呼び出すと、繰り返しの回数に必要な何十万もの要素を持ったリストを事前にメモリ上に用意するからです。そのため、このような場合はxrange()を使いました。xrange()はイテレータ風のオブジェクトを生成します。数を順番に生成するだけなので、すべての要素をメモリ上に置かないため、メモリの使用効率上利点があるのです。3.0では、range()関数がイテレータ風のオブジェクトを返すようになり、xrange()が不要になったため廃止になりました。状況によって使い分ける必要があった2つの関数が1つに統合されて、より一貫性が増したわけです。3.0でやっと統合されたことになります。range()だけでなく、map()やfilter()、zip()といったリストを返していた関数も、イテレータを返すようになります。map()関数では、引数として与えたシーケンスに対して、一度に処理をするのではなく、逐次処理をするようになるわけです。辞書のような組み込み型のメソッドにもリストを返すものがありました。辞書オブジェクトのキー一覧を返すkeys()、値一覧を返すvalues()、キーと値のペアを一覧で返すitems()といったメソッドがその例です。これらのメソッドは、リストより軽量で粒度の低いイテレータ風のviewと呼ばれるオブジェクトを返すようになりました。3で辞書オブジェクトのkeys()を呼び出すと、dict_keysという名前のオブジェクトが返ってきます。これがviewと呼ばれるタイプのオブジェクトです。イテレータと同じ働きをして、イテレーションのたびに次のオブジェクトを返します。自分自身では値を保持せず、呼び出し元の辞書オブジェクトにリファレンスを張るような形でキー一覧を返します。3.0で、メソッドの返すviewを変数に代入してみましょう。'd']このように、viewオブジェクトは辞書本体とのリファレンスを保っているだけなので、辞書本体にキーが追加されるとviewの結果も更新されます。keys()が返すキーの一覧は、辞書オブジェクト自体が内部に持っています。2までは、辞書オブジェクトがすでに持っている情報を、わざわざリストに変換していたわけです。Pythonのリストは、メモリ領域伸張のコストを下げるため、あらかじめ要素数以上のメモリ空間を占有します。表面で見える以上に粒度の大きなオブジェクトなのです。リストオブジェクトの生成にオーバーヘッドが大きいため、もっと粒度の低いオブジェクトを使うべきという議論がありました。そのため、今回のような仕様変更が行われたのです。リストを返していたメソッドや組み込み関数が、イテレータやviewを返すようになったため、リストであることを期待したコードは修正が必要になります。関数の戻り値に直接インデックスを指定するようなコードは、動かなくなってしまいますので注意が必要です。メールマガジンをご購読ください。申し込みページへITmediaはアイティメディア株式会社の登録商標です。