Python3.1の新機能
- 著者
- レイモンドヘッティンガー
この記事では、3.0と比較したPython3.1の新機能について説明します。
PEP 372:注文された辞書
通常のPython辞書は、キーと値のペアを任意の順序で繰り返し処理します。 何年にもわたって、多くの作成者が、キーが最初に挿入された順序を記憶する代替の実装を作成してきました。 これらの実装の経験に基づいて、新しい collections.OrderedDict クラスが導入されました。
OrderedDict APIは、通常の辞書と実質的に同じですが、キーが最初に挿入された日時に応じて、保証された順序でキーと値を繰り返し処理します。 新しいエントリが既存のエントリを上書きする場合、元の挿入位置は変更されません。 エントリを削除して再挿入すると、最後に移動します。
標準ライブラリは、いくつかのモジュールで順序付けられた辞書の使用をサポートするようになりました。 configparser モジュールはデフォルトでそれらを使用します。 これにより、構成ファイルを読み取り、変更してから、元の順序で書き戻すことができます。 collections.namedtuple()の _asdict()メソッドは、基になるタプルインデックスと同じ順序で表示される値を持つ順序付きディクショナリを返すようになりました。 json モジュールは object_pairs_hook で構築されており、デコーダーがOrderedDictsを構築できるようになっています。 PyYAML などのサードパーティツールのサポートも追加されました。
PEP 378:数千の区切り文字のフォーマット指定子
組み込みの format()関数と str.format()メソッドは、ミニ言語を使用します。このミニ言語には、ロケールを認識しない簡単な方法で数値をフォーマットします。千のセパレータ。 これは、プログラムの出力を人間化する方法を提供し、そのプロフェッショナルな外観と読みやすさを向上させます。
>>> 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 です。
ドット、スペース、アポストロフィ、アンダースコアなどの代替区切り文字を指定する方法についての議論が進行中です。 ロケール対応アプリケーションは、数千のセパレーターをすでにサポートしている既存の n 形式指定子を使用する必要があります。
も参照してください
- PEP 378 -数千の区切り文字のフォーマット指定子
- Raymond Hettingerによって作成され、EricSmithとMarkDickinsonによって実装されたPEP。
その他の言語の変更
コアPython言語に加えられたいくつかの小さな変更は次のとおりです。
__main__.py
ファイルを含むディレクトリとzipアーカイブは、それらの名前をインタプリタに渡すことで直接実行できるようになりました。 ディレクトリ/ zipファイルは、sys.pathの最初のエントリとして自動的に挿入されます。 (AndyChuによる提案と初期パッチ; PhillipJによる改訂パッチ。 EbyとNickCoghlan; :issue: `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
(Fredrik Johansson、Victor Stinner、Raymond Hettinger、およびMarkDickinsonによる寄稿; :issue: `3439` 。)
format()文字列のフィールドに自動的に番号を付けることができるようになりました。
>>> 'Sir {} of {}'.format('Gallahad', 'Camelot') 'Sir Gallahad of Camelot'
以前は、文字列には
'Sir {0} of {1}'
などの番号付きフィールドが必要でした。(EricSmithによる寄稿; :issue: `5237` 。)
string.maketrans()
関数は非推奨になり、新しい静的メソッド bytes.maketrans()および bytearray.maketrans()に置き換えられました。 この変更により、 string モジュールでサポートされているタイプに関する混乱が解消されます。 現在、 str 、 bytes 、および bytearray には、それぞれ独自の maketrans および translate メソッドと中間変換テーブルがあります。適切なタイプの。(GeorgBrandlによる寄稿; :issue: `5675` 。)
with ステートメントの構文で、1つのステートメントで複数のコンテキストマネージャーを使用できるようになりました。
>>> with open('mylog.txt') as infile, open('a.out', 'w') as outfile: ... for line in infile: ... if '<critical>' in line: ... outfile.write(line)
新しい構文では、
contextlib.nested()
関数は不要になり、非推奨になりました。(GeorgBrandlとMattiasBrändströmによる寄稿; appspot issue 53094 。)
round(x, n)
は整数を返すようになりました。 以前はフロートを返しました:>>> round(1123, -2) 1100
(MarkDickinsonによる寄稿; :issue: `4707` 。)
Pythonは、David Gayのアルゴリズムを使用して、値を変更しない最短の浮動小数点表現を見つけるようになりました。 これは、2進浮動小数点数を取り巻く混乱の一部を軽減するのに役立つはずです。
重要性は、
1.1
のように、2進浮動小数点に完全に相当するものがない数値で簡単にわかります。 正確に同等のものがないため、float('1.1')
のような式は、16進数の0x1.199999999999ap+0
または10進数の1.100000000000000088817841970012523233890533447265625
である最も近い表現可能な値に評価されます。 その最も近い値は、その後の浮動小数点計算で使用されていました。新しいのは、番号の表示方法です。 以前は、Pythonは単純なアプローチを使用していました。
repr(1.1)
の値は、format(1.1, '.17g')
として計算され、'1.1000000000000001'
と評価されました。 17桁を使用する利点は、IEEE-754保証に依存して、eval(repr(1.1))
が元の値に正確にラウンドトリップすることを保証することでした。 不利な点は、多くの人が出力を混乱させることに気づいたことです(バイナリ浮動小数点表現の本質的な制限をPython自体の問題であると誤解しています)。repr(1.1)
の新しいアルゴリズムはよりスマートで、'1.1'
を返します。 事実上、すべての同等の文字列表現(同じ基になるfloat値で格納されるもの)を検索し、最短の表現を返します。新しいアルゴリズムは、可能な場合はよりクリーンな表現を生成する傾向がありますが、基になる値は変更されません。 したがって、表現が別のことを示唆している場合でも、
1.1 + 2.2 != 3.3
は依然として当てはまります。新しいアルゴリズムは、基礎となる浮動小数点実装の特定の機能に依存します。 必要な機能が見つからない場合は、古いアルゴリズムが引き続き使用されます。 また、テキストピクルスプロトコルは、古いアルゴリズムを使用してクロスプラットフォームの移植性を保証します。
(EricSmithとMarkDickinsonによる寄稿; :issue: `1580` )
新規、改善、および非推奨のモジュール
collections.Counter クラスを追加して、シーケンス内または反復可能な一意のアイテムの便利なカウントをサポートします。
>>> Counter(['red', 'blue', 'red', 'green', 'blue', 'blue']) Counter({'blue': 3, 'red': 2, 'green': 1})
(RaymondHettingerによる寄稿; :issue: `1696199` 。)
Tkをテーマにしたウィジェットセットにアクセスするための新しいモジュール tkinter.ttk を追加しました。 ttkの基本的な考え方は、ウィジェットの動作を実装するコードを、その外観を実装するコードから可能な限り分離することです。
(GuilhermePoloによる寄稿; :issue: `2983` 。)
gzip.GzipFile および bz2.BZ2File クラスがコンテキスト管理プロトコルをサポートするようになりました。
>>> # Automatically close file after writing >>> with gzip.GzipFile(filename, "wb") as f: ... f.write(b"xxx")
(Antoine Pitrouによる寄稿。)
decimal モジュールは、バイナリ float からdecimalオブジェクトを作成するためのメソッドをサポートするようになりました。 変換は正確ですが、意外な場合もあります。
>>> Decimal.from_float(1.1) Decimal('1.100000000000000088817841970012523233890533447265625')
長い小数の結果は、 1.1 に格納されている実際の2進小数を示しています。 1.1 をバイナリで正確に表すことができないため、分数には多くの桁があります。
(RaymondHettingerとMarkDickinsonによる寄稿。)
itertools モジュールは2つの新しい機能を拡張しました。 itertools.combinations_with_replacement()関数は、順列やデカルト積を含む組み合わせ論を生成するための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)]
(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)]
(RaymondHettingerによる寄稿; :issue: `1818` 。)
re.sub()、 re.subn()、および re.split()関数がflagsパラメーターを受け入れるようになりました。
(Gregory Smithによる寄稿。)
logging モジュールは、ロギングを使用していないが、ロギングを使用しているライブラリコードを呼び出しているアプリケーションに対して、単純な logging.NullHandler クラスを実装するようになりました。 nullハンドラーを設定すると、「ロガーfooのハンドラーが見つかりませんでした」などの誤った警告が抑制されます。
>>> h = logging.NullHandler() >>> logging.getLogger("foo").addHandler(h)
(VinaySajipによる寄稿; :issue: `4384` )。
-m
コマンドラインスイッチをサポートする runpy モジュールは、パッケージ名が指定されたときに__main__
サブモジュールを検索して実行することにより、パッケージの実行をサポートするようになりました。(AndiVajdaによる寄稿; :issue: `4195` 。)
pdb モジュールは、 zipimport (またはその他の準拠 PEP 302 ローダー)を介してロードされたソースコードにアクセスして表示できるようになりました。
(AlexanderBelopolskyによる寄稿; :issue: `4201` 。)
functools.partial オブジェクトをpickle化できるようになりました。
(AntoinePitrouとJesseNollerによって提案されました。 JackDiederichによって実装されました。 :issue: `5228` 。)
シンボルの pydoc ヘルプトピックを追加して、
help('@')
がインタラクティブ環境で期待どおりに機能するようにします。(DavidLabanによる寄稿; :issue: `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
さらに、
assertSetEqual()
、assertDictEqual()
、assertDictContainsSubset()
、assertListEqual()
、assertTupleEqual()
、assertSequenceEqual()
など、いくつかの新しいアサーションメソッドが追加されました。 ]、assertRaisesRegexp()
、assertIsNone()
、およびassertIsNotNone()
。(BenjaminPetersonとAntoinePitrouによる寄稿。)
io モジュールには、
seek()
メソッドSEEK_SET
、SEEK_CUR
、およびSEEK_END
の3つの新しい定数があります。sys.version_info タプルは、名前付きタプルになりました。
>>> sys.version_info sys.version_info(major=3, minor=1, micro=0, releaselevel='alpha', serial=2)
(RossLightによる寄稿; :issue: `4285` 。)
nntplib および imaplib モジュールがIPv6をサポートするようになりました。
(DerekMorrによる寄稿; :issue: `1655` および:issue:` 1664` 。)
pickle モジュールは、プロトコル2以下で使用した場合にPython2.xとの相互運用性を向上させるように調整されています。 標準ライブラリの再編成により、多くのオブジェクトの正式な参照が変更されました。 たとえば、Python2の
__builtin__.set
は、Python3ではbuiltins.set
と呼ばれます。 この変更により、異なるバージョンのPython間でデータを共有する取り組みが混乱しました。 ただし、プロトコル2以下が選択されると、ピッカーはロードとダンプの両方に古いPython2名を自動的に使用します。 この再マッピングはデフォルトでオンになっていますが、 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.'
この変更の残念ながら避けられない副作用は、Python3.1で生成されたプロトコル2のピクルスがPython3.0で読み取れないことです。 Python 3.xの実装間でデータを移行する場合は、最新のpickleプロトコルであるプロトコル3を使用する必要があります。これは、Python2.xとの互換性を維持しようとしないためです。
(AlexandreVassalottiとAntoinePitrouによる寄稿、:issue: `6137` 。)
新しいモジュール importlib が追加されました。 これは、 import ステートメントとそれに対応する __ import __()関数の完全でポータブルな純粋なPythonリファレンス実装を提供します。 これは、インポート中に発生するアクションを文書化および定義する上での実質的な前進を表しています。
(Brett Cannonによる寄稿。)
最適化
主要なパフォーマンスの強化が追加されました。
新しいI / Oライブラリ( PEP 3116 で定義)は主にPythonで記述されており、Python3.0では問題のあるボトルネックであることがすぐに判明しました。 Python 3.1では、I / Oライブラリは完全にCで書き直されており、手元のタスクに応じて2〜20倍高速です。 純粋なPythonバージョンは、
_pyio
モジュールを介して実験目的で引き続き利用できます。(Amaury Forgeotd'ArcとAntoinePitrouによる寄稿。)
追跡不可能なオブジェクトのみを含むタプルとディクテーションがガベージコレクターによって追跡されないように、ヒューリスティックを追加しました。 これにより、データ型の特定の使用法に応じて、コレクションのサイズを削減できるため、長時間実行されるプログラムでのガベージコレクションのオーバーヘッドを削減できます。
(Antoine Pitrouによる寄稿、:issue: `4688` 。)
それをサポートするコンパイラ(特にgcc、SunPro、icc)で
--with-computed-gotos
という名前の構成オプションを有効にすると、バイトコード評価ループは、システムに応じて最大20%のスピードアップを提供する新しいディスパッチメカニズムでコンパイルされます、コンパイラ、およびベンチマーク。(Antoine Pitrouと他の多くの参加者による寄稿、:issue: `4753` )。
UTF-8、UTF-16、およびLATIN-1のデコードは、2〜4倍高速になりました。
(AntoinePitrouとAmauryForgeot d'Arcによる寄稿、:issue: `4868` 。)
json モジュールにC拡張機能が追加され、パフォーマンスが大幅に向上しました。 さらに、APIが変更され、jsonが str でのみ機能し、 bytes では機能しないようになりました。 この変更により、モジュールはUnicodeで定義されている JSON仕様と厳密に一致します。
(Bob Ippolitoによって寄稿され、AntoinePitrouとBenjaminPetersonによってPy3.1に変換されました; :issue: `4136` 。)
Unpicklingは、pickle化されたオブジェクトの属性名をインターンするようになりました。 これにより、メモリが節約され、ピクルスを小さくすることができます。
(JakeMcGuireとAntoinePitrouによる寄稿; :issue: `5084` 。)
ビルドとCAPIの変更
PythonのビルドプロセスとCAPIへの変更は次のとおりです。
整数は、基数2 ** 15または基数2 ** 30のいずれかに内部的に格納されるようになりました。基数は、ビルド時に決定されます。 以前は、それらは常に基数2 ** 15に格納されていました。 ベース2 ** 30を使用すると、64ビットマシンでのパフォーマンスが大幅に向上しますが、32ビットマシンでのベンチマーク結果はまちまちです。 したがって、デフォルトでは、64ビットマシンではベース2 ** 30を使用し、32ビットマシンではベース2 ** 15を使用します。 Unixでは、このデフォルトをオーバーライドするために使用できる新しい構成オプション
--enable-big-digits
があります。パフォーマンスの向上とは別に、この変更はエンドユーザーには見えないはずです。ただし、テストとデバッグの目的で、内部形式に関する情報を提供し、1桁あたりのビット数を示す新しい sys.int_info があります。各桁を格納するために使用されるCタイプのバイト単位のサイズ:
>>> import sys >>> sys.int_info sys.int_info(bits_per_digit=30, sizeof_digit=4)
(MarkDickinsonによる寄稿; :issue: `4258` 。)
PyLong_AsUnsignedLongLong()関数は、 TypeError ではなく OverflowError を発生させることにより、負の pylong を処理するようになりました。
(MarkDickinsonとLisandroDalcrinによる寄稿; :issue: `5175` 。)
非推奨の
PyNumber_Int()
。 代わりに PyNumber_Long()を使用してください。(MarkDickinsonによる寄稿; :issue: `4910` 。)
非推奨の関数
PyOS_ascii_strtod()
およびPyOS_ascii_atof()
を置き換えるために、新しい PyOS_string_to_double()関数が追加されました。(MarkDickinsonによる寄稿; :issue: `5914` 。)
PyCObject
APIの代わりに PyCapsule を追加しました。 主な違いは、新しい型には、入力の安全性情報を渡すための明確に定義されたインターフェイスと、デストラクタを呼び出すためのそれほど複雑でない署名があることです。 古いタイプには問題のあるAPIがあり、現在は非推奨です。(LarryHastingsによる寄稿; :issue: `5630` 。)
Python3.1への移植
このセクションでは、コードの変更が必要になる可能性のある、前述の変更とその他のバグ修正を示します。
新しい浮動小数点文字列表現は、既存のdoctestを壊す可能性があります。 例えば:
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 **********************************************************************
プロトコル2以下のpickleモジュールでの自動名前再マッピングにより、Python3.1のpickleがPython3.0で読み取れなくなる可能性があります。 1つの解決策は、プロトコル3を使用することです。 別の解決策は、 fix_imports オプションを
False
に設定することです。 詳細については、上記の説明を参照してください。