What's New In Python 3.1¶
- 著者:
Raymond Hettinger
この記事では 3.0 と比較した Python 3.1 の新機能を解説します。Python 3.1 は2009年6月27日にリリースされました。
PEP 372: 順序付き辞書¶
通常の Python 辞書は、 key/value ペアを不定の順序でイテレートします。何年にもわたり、いろいろな人が key の挿入順を保存する辞書の別実装を書いてきました。その経験に基づき、新しい OrderedDict
クラスが導入されました。
OrderedDict API は通常の辞書と同じインターフェースを提供していますが、 key/value をイテレートするときに key が最初に挿入された順番になることが保証されています。新しいエントリが既存のエントリを上書きした場合は、元の挿入順序が保持されます。エントリを削除して再挿入すると、順序は一番最後に移動します。
標準ライブラリのいくつかのモジュールで、順序付き辞書の利用がサポートされています。configparser
モジュールはデフォルトで順序付き辞書を使います。設定ファイルを読み込み、編集した後、元の順序で書きなおすことができます。collections.namedtuple()
の _asdict() メソッドは、タプルの順序と同じ順序の順序付き辞書を返すようになりました。json
モジュールのデコーダーが OrderedDict をビルドするのをサポートするために、 JSONDecoder
クラスのコンストラクタに object_pairs_hook 引数が追加されました。 PyYAML などの外部のライブラリでもサポートされています。
参考
- PEP 372 - 順序付き辞書
PEP written by Armin Ronacher and Raymond Hettinger. Implementation written by Raymond Hettinger.
順序付き辞書は挿入順序を記憶するので、ソートと組み合わせて使うことで、ソートされた辞書を作れます:
>>> # regular unsorted dictionary
>>> d = {'banana': 3, 'apple':4, 'pear': 1, 'orange': 2}
>>> # dictionary sorted by key
>>> OrderedDict(sorted(d.items(), key=lambda t: t[0]))
OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])
>>> # dictionary sorted by value
>>> OrderedDict(sorted(d.items(), key=lambda t: t[1]))
OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])
>>> # dictionary sorted by length of the key string
>>> OrderedDict(sorted(d.items(), key=lambda t: len(t[0])))
OrderedDict([('pear', 1), ('apple', 4), ('orange', 2), ('banana', 3)])
この新しい順序付き辞書は、項目が削除されてもソートされた順序を保持します。しかし、キーが追加されるとき、そのキーは最後に追加され、ソートは保持されません。
PEP 378: 1000区切りのための書式指定子¶
組み込みの format()
関数と str.format()
メソッドが使うミニ言語に、単純でロケールに依存しない 1000 区切りカンマの書式化が追加されました。これによって簡単にプログラムの出力を、その玄人ちっくな見た目を改善してひとさまにとって読みやすいものに出来ます:
>>> format(1234567, ',d')
'1,234,567'
>>> format(1234567.89, ',.2f')
'1,234,567.89'
>>> format(12345.6 + 8901234.12j, ',f')
'12,345.600000+8,901,234.120000j'
>>> format(Decimal('1234567.89'), ',f')
'1,234,567.89'
これをサポートする型は int
, float
, complex
, decimal.Decimal
です。
ドットやら空白やらアポストロフィやらあるいはアンダースコアなどの他のセパレータをどうやって指定するかの議論は水面下にありますが、ロケールに従う必要があるアプリケーションは、1000区切りセパレータについていくつかのサポートを既に持っている既存の n 指定子を使うべきです。
参考
- PEP 378 - 1000区切りのための書式指定子
PEP written by Raymond Hettinger and implemented by Eric Smith and Mark Dickinson.
その他の言語変更¶
Python 言語コアに小さな変更がいくつか行われました:
__main__.py
を含むディレクトと zip アーカイブを、その名前をインタプリタに渡すことで直接実行出来るようになりました。そのディレクトリと zip ファイルは自動的に sys.path エントリの先頭に挿入されます。(Suggestion and initial patch by Andy Chu; revised patch by Phillip J. Eby and Nick Coghlan; bpo-1739468.)int()
型にbit_length
メソッドが追加されました。 このメソッドはその値を二進数で表現するのに必要なビット数を返します:>>> n = 37 >>> bin(37) '0b100101' >>> n.bit_length() 6 >>> n = 2**123-1 >>> n.bit_length() 123 >>> (n+1).bit_length() 124
(Contributed by Fredrik Johansson, Victor Stinner, Raymond Hettinger, and Mark Dickinson; bpo-3439.)
format()
文字列のフィールドに自動的に番号が振られるようになりました:>>> 'Sir {} of {}'.format('Gallahad', 'Camelot') 'Sir Gallahad of Camelot'
以前は、文字列は
'Sir {0} of {1}'
のようにフィールドに番号を振らなければなりませんでした。(Contributed by Eric Smith; bpo-5237.)
The
string.maketrans()
function is deprecated and is replaced by new static methods,bytes.maketrans()
andbytearray.maketrans()
. This change solves the confusion around which types were supported by thestring
module. Now,str
,bytes
, andbytearray
each have their own maketrans and translate methods with intermediate translation tables of the appropriate type.(Contributed by Georg Brandl; bpo-5675.)
with
文のシンタックスは一つの文で複数のコンテキストマネージャを使えるようになりました:>>> with open('mylog.txt') as infile, open('a.out', 'w') as outfile: ... for line in infile: ... if '<critical>' in line: ... outfile.write(line)
With the new syntax, the
contextlib.nested()
function is no longer needed and is now deprecated.(Georg Brandl と Mattias Brändström の貢献; appspot issue 53094.)
round(x, n)
は x が整数の場合、整数を返すようになりました。以前は浮動小数点を返していました:>>> round(1123, -2) 1100
(Contributed by Mark Dickinson; bpo-4707.)
Python now uses David Gay's algorithm for finding the shortest floating-point representation that doesn't change its value. This should help mitigate some of the confusion surrounding binary floating-point numbers.
The significance is easily seen with a number like
1.1
which does not have an exact equivalent in binary floating point. Since there is no exact equivalent, an expression likefloat('1.1')
evaluates to the nearest representable value which is0x1.199999999999ap+0
in hex or1.100000000000000088817841970012523233890533447265625
in decimal. That nearest value was and still is used in subsequent floating-point calculations.What is new is how the number gets displayed. Formerly, Python used a simple approach. The value of
repr(1.1)
was computed asformat(1.1, '.17g')
which evaluated to'1.1000000000000001'
. The advantage of using 17 digits was that it relied on IEEE-754 guarantees to assure thateval(repr(1.1))
would round-trip exactly to its original value. The disadvantage is that many people found the output to be confusing (mistaking intrinsic limitations of binary floating-point representation as being a problem with Python itself).新しいアルゴリズムでは
repr(1.1)
はより賢明で'1.1'
を返します。実際的には、これは全ての等価な文字列表現 (前提となる同じ浮動小数点数に戻るもの) を探し、そして一番短い表現を返します。新アルゴリズムは、可能な限りよりわかりやすい表現を生み出す傾向がありますが、元の値を変更しません。ですから
1.1 + 2.2 != 3.3
は表示がどうであれ、今でも問題です。The new algorithm depends on certain features in the underlying floating-point implementation. If the required features are not found, the old algorithm will continue to be used. Also, the text pickle protocols assure cross-platform portability by using the old algorithm.
(Contributed by Eric Smith and Mark Dickinson; bpo-1580)
新たなモジュール、改良されたモジュール、非推奨のモジュール¶
シーケンスまたはイテラブル内にある一意な要素を数え上げるのに便利な
collections.Counter
クラスが追加されました:>>> Counter(['red', 'blue', 'red', 'green', 'blue', 'blue']) Counter({'blue': 3, 'red': 2, 'green': 1})
(Contributed by Raymond Hettinger; bpo-1696199.)
Tk のテーマ付きウィジェットへのアクセスを提供する、新しい
tkinter.ttk
モジュールが追加されました。tkinter.ttk
の基本的なアイディアは、拡張可能性のためにウィジェットの動作を実装するコードと見た目を記述するコードを分離することです。(Contributed by Guilherme Polo; bpo-2983.)
gzip.GzipFile
とbz2.BZ2File
クラスはコンテキストマネジメントプロトコルをサポートするようになりました:>>> # Automatically close file after writing >>> with gzip.GzipFile(filename, "wb") as f: ... f.write(b"xxx")
(Contributed by Antoine Pitrou.)
decimal
モジュールが二進float
から decimal オブジェクトを生成するメソッドをサポートしました。 変換は正確ですが時に意外なことがあります:>>> Decimal.from_float(1.1) Decimal('1.100000000000000088817841970012523233890533447265625')
長い十進の結果が、 1.1 を記憶するための現実の二進での端数を表しています。 1.1 は二進数で正確に表現出来ないので、端数は十進表現でとても多くの桁数になっています。
(Contributed by Raymond Hettinger and Mark Dickinson.)
itertools
に 2 つの関数が追加されました。itertools.combinations_with_replacement()
関数は、置換 (順列, permutation) や直積 (Cartesian product) を含む組合せ論の 4 つの生成関数のうちの 1 つです。itertools.compress()
関数は APL の同名機能の模倣品です。また、既存のitertools.count()
関数は新たにオプショナルな step 引数を取るようになり、そして数え方にfractions.Fraction
やdecimal.Decimal
を含む任意の数値型を使えるようになりました。>>> [p+q for p,q in combinations_with_replacement('LOVE', 2)] ['LL', 'LO', 'LV', 'LE', 'OO', 'OV', 'OE', 'VV', 'VE', 'EE'] >>> list(compress(data=range(10), selectors=[0,0,1,1,0,1,0,1,0,0])) [2, 3, 5, 7] >>> c = count(start=Fraction(1,2), step=Fraction(1,6)) >>> [next(c), next(c), next(c), next(c)] [Fraction(1, 2), Fraction(2, 3), Fraction(5, 6), Fraction(1, 1)]
(Contributed by Raymond Hettinger.)
collections.namedtuple()
が新たにキーワード引数 rename をサポートし、これにより不正なフィールド名を自動で _0, _1, ... といった位置による名前に変換することが出来ます。これはフィールド名が何か外部ソースに基いて作られる場合に有用です。例えば CSV のヘッダ、SQL のフィールドリスト、あるいはユーザ入力などです:>>> query = input() SELECT region, dept, count(*) FROM main GROUPBY region, dept >>> cursor.execute(query) >>> query_fields = [desc[0] for desc in cursor.description] >>> UserQuery = namedtuple('UserQuery', query_fields, rename=True) >>> pprint.pprint([UserQuery(*row) for row in cursor]) [UserQuery(region='South', dept='Shipping', _2=185), UserQuery(region='North', dept='Accounting', _2=37), UserQuery(region='West', dept='Sales', _2=419)]
(Contributed by Raymond Hettinger; bpo-1818.)
re.sub()
、re.subn()
およびre.split()
関数は flags 引数を受け取るようになりました。(Contributed by Gregory Smith.)
logging を自身では使わずとも使用ライブラリがそうしているようなアプリケーションのために、
logging
モジュールが単純なlogging.NullHandler
を実装しました。null ハンドラをセットアップすることは、 "No handlers could be found for logger foo" のような警告を抑制します。>>> h = logging.NullHandler() >>> logging.getLogger("foo").addHandler(h)
(Contributed by Vinay Sajip; bpo-4384).
コマンドラインスイッチ
-m
をサポートしているrunpy
がパッケージの実行をサポートするようになりました。パッケージ名が与えられると__main__
サブモジュールを探し出して実行します。(Contributed by Andi Vajda; bpo-4195.)
pdb
モジュールがzipimport
(あるいはなにかほかの PEP 302 準拠ローダ) でロードされたモジュールのソースコードにアクセスでき、表示できるようになりました。(Contributed by Alexander Belopolsky; bpo-4201.)
functools.partial
オブジェクトが pickle 化出来るようになりました。
(Suggested by Antoine Pitrou and Jesse Noller. Implemented by Jack Diederich; bpo-5228.)
シンボルのための
pydoc
ヘルプトピックが追加されました。これで対話環境でhelp('@')
などが期待通りの働きをします (---訳注: 実装としては pydoc_data パッケージのこと。pydoc_data/topics.py
に docstring からは生成出来ない、シンボルについてのドキュメントが収められています ---)。(Contributed by David Laban; bpo-4739.)
unittest
に特定のテストメソッドやテストクラス全体をスキップする仕組みのサポートが追加されました。さらに、この機能はテスト結果を「意図的な失敗」とすることができ、テストが失敗してもTestResult
の失敗数にはカウントされなくなります:class TestGizmo(unittest.TestCase): @unittest.skipUnless(sys.platform.startswith("win"), "requires Windows") def test_gizmo_on_windows(self): ... @unittest.expectedFailure def test_gimzo_without_required_library(self): ...
また例外についてのテストが、
with
文で使えるコンテキストマネージャとして増強されました:def test_division_by_zero(self): with self.assertRaises(ZeroDivisionError): x / 0
In addition, several new assertion methods were added including
assertSetEqual()
,assertDictEqual()
,assertDictContainsSubset()
,assertListEqual()
,assertTupleEqual()
,assertSequenceEqual()
,assertRaisesRegexp()
,assertIsNone()
, andassertIsNotNone()
.(Contributed by Benjamin Peterson and Antoine Pitrou.)
The
io
module has three new constants for theseek()
method:SEEK_SET
,SEEK_CUR
, andSEEK_END
.sys.version_info
タプルが名前付きタプルになりました。>>> sys.version_info sys.version_info(major=3, minor=1, micro=0, releaselevel='alpha', serial=2)
(Contributed by Ross Light; bpo-4285.)
The
nntplib
andimaplib
modules now support IPv6.pickle
を、プロトコル 2 以下を使う際に Python 2.x との相互運用に順応するようにしました。標準ライブラリの再編成はたくさんのオブジェクトへの公式な参照を変えました。例えば Python 2 の__builtin__.set
は Python 3 ではbuiltins.set
です。この変化は異なる Python バージョン間でのデータ共有の取り組みを複雑にしました。ですが今回のこの修正により、プロトコル 2 以下を選んだ場合は pickler は自動的にロード時もダンプ時も古い Python 2 命名を使うようになります。この再マッピングはデフォルトで有効になりますが、 fix_imports オプションで無効に出来ます:>>> s = {1, 2, 3} >>> pickle.dumps(s, protocol=0) b'c__builtin__\nset\np0\n((lp1\nL1L\naL2L\naL3L\natp2\nRp3\n.' >>> pickle.dumps(s, protocol=0, fix_imports=False) b'cbuiltins\nset\np0\n((lp1\nL1L\naL2L\naL3L\natp2\nRp3\n.'
不幸にも、そして避けられないこの変更による副作用は、Python 3.1 によって生成されたプロトコル 2 pickle が Python 3.0 で読めなくなるであろうことです。Python 2.x との互換性を維持するつもりがないのであれば、Python 3.x 実装間でのデータ移行では最新 pickle プロトコルバージョン 3 を使うべきです。
(Contributed by Alexandre Vassalotti and Antoine Pitrou, bpo-6137.)
新規モジュール
importlib
が追加されました。import
文とその相棒の__import__()
関数の、完全で移植性が高いピュア Python 参照実装を提供しています。これはインポートで行う動作の文書化と定義における、確かな前進です。(Contributed by Brett Cannon.)
最適化¶
大きな性能向上がありました:
The new I/O library (as defined in PEP 3116) was mostly written in Python and quickly proved to be a problematic bottleneck in Python 3.0. In Python 3.1, the I/O library has been entirely rewritten in C and is 2 to 20 times faster depending on the task at hand. The pure Python version is still available for experimentation purposes through the
_pyio
module.(Contributed by Amaury Forgeot d'Arc and Antoine Pitrou.)
Added a heuristic so that tuples and dicts containing only untrackable objects are not tracked by the garbage collector. This can reduce the size of collections and therefore the garbage collection overhead on long-running programs, depending on their particular use of datatypes.
(Contributed by Antoine Pitrou, bpo-4688.)
Enabling a configure option named
--with-computed-gotos
on compilers that support it (notably: gcc, SunPro, icc), the bytecode evaluation loop is compiled with a new dispatch mechanism which gives speedups of up to 20%, depending on the system, the compiler, and the benchmark.(Contributed by Antoine Pitrou along with a number of other participants, bpo-4753).
UTF-8, UTF-16 ならびに LATIN-1 のデコーディングが2から4倍速くなりました。
(Antoine Pitrou と Amaury Forgeot d'Arc の貢献, bpo-4868.)
The
json
module now has a C extension to substantially improve its performance. In addition, the API was modified so that json works only withstr
, not withbytes
. That change makes the module closely match the JSON specification which is defined in terms of Unicode.(Contributed by Bob Ippolito and converted to Py3.1 by Antoine Pitrou and Benjamin Peterson; bpo-4136.)
Unpickling now interns the attribute names of pickled objects. This saves memory and allows pickles to be smaller.
(Contributed by Jake McGuire and Antoine Pitrou; bpo-5084.)
IDLE¶
IDLE のフォーマットメニューに、ソースコードから末尾の空白を取り除くことが出来るオプションが追加されました。
(Contributed by Roger D. Serwy; bpo-5150.)
ビルドならびに C API の変更¶
Python のビルド過程と C API の変更は以下の通りです:
整数の内部格納方式が
2**15
ベースと2**30
ベースのいずれかになりました。 これはビルド時に決定されます。 以前は常に2**15
ベースで格納されていました。2**30
ベースにすると 64 bit マシンでは性能が有意に向上しますが、 32 bit マシンでのベンチマーク結果には向上も低下もあります。 そのため、デフォルトでは 64 bit マシンで2**30
ベースを、 32 bit マシンで2**15
ベースを使用します。 Unix では新たな configure オプション--enable-big-digits
が追加されました。 これにより上記のデフォルトを上書き出来ます。この変更は性能向上以外ではエンドユーザには分からないはずですが、例外が1つあります。 テストおよびデバッグ目的で内部形式の情報を提供する
sys.int_info
が追加されましたが、これにより数字あたりのビット数と各数字の格納に使われる C の型のバイトサイズが分かります:>>> import sys >>> sys.int_info sys.int_info(bits_per_digit=30, sizeof_digit=4)
(Contributed by Mark Dickinson; bpo-4258.)
PyLong_AsUnsignedLongLong()
関数は負の pylong に対しTypeError
ではなくOverflowError
を送出するようになりました。(Contributed by Mark Dickinson and Lisandro Dalcrin; bpo-5175.)
PyNumber_Int()
が非推奨になりました。代わりにPyNumber_Long()
を使用してください。(Contributed by Mark Dickinson; bpo-4910.)
非推奨の関数
PyOS_ascii_strtod()
およびPyOS_ascii_atof()
を置き換えるために新しくPyOS_string_to_double()
関数が追加されました。(Contributed by Mark Dickinson; bpo-5914.)
PyCObject
API を置き換えるものとして、PyCapsule
が追加されました。主な違いとしては、新しい型は、型安全に情報を渡すための良く定義されたインターフェースを持ち、また、デストラクタの呼び出しのシグネチャの複雑さが小さくなっています。古い型は問題のある API で、今では非推奨です。(Contributed by Larry Hastings; bpo-5630.)
Python 3.1 への移植¶
このセクションでは前述の変更とバグフィックスにより必要となるかもしれないコードの変更を列挙します:
The new floating-point string representations can break existing doctests. For example:
def e(): '''Compute the base of natural logarithms. >>> e() 2.7182818284590451 ''' return sum(1/math.factorial(x) for x in reversed(range(30))) doctest.testmod() ********************************************************************** Failed example: e() Expected: 2.7182818284590451 Got: 2.718281828459045 **********************************************************************
pickle モジュールがプロトコルバージョン 2 以下で自動的に名前の再対応付けを行うので、Python 3.1 で pickle 化すると Python 3.0 で読めなくなります。一つの解決策はプロトコル 3 を使うことです。もう一つは fix_imports オプションを
False
にセットすることです。上述の議論を参照してください。