もっと知りたいPython3000

第2回 組み込み型への変更

この記事を読むのに必要な時間:およそ 2 分

Pythonでは,基本的なデータ型を組み込み型(Builtin Types)」として提供しています。文字列や数値といった基本的なデータ型だけでなく,リストや辞書,集合(Set)型のような構造を持ったデータ型が組み込み型として用意されています。

Python 2.x世代の組み込み型には,言語としての一貫性を崩す仕様がいくつか存在しているのも事実です。そのような不整合の多くは,後付けの仕様追加が原因となっています。

Python 3000では,組み込み型の設計にメスが入り,より一貫性のある仕様に見直しが図られています。今回は,組み込み型を中心に,Python 3000での変更点を概観したいと思います。

Unicodeベースの文字列型

Python 3000では,文字列型に大きな変更が加えられます。文字列(str)型がUnicodeベースの型に変更されるのです。

2.xまでは,Pythonには2種類の文字列型がありました。エンコードを考慮しない8ビット文字列としてのstr型と,Unicodeベースのunicode型です。

Python 3.0では,従来のstr型がunicode型に置き換わります。それに伴って,unicode型と,「u"~"」というリテラル表記は廃止されます。

標準の文字列型がUnicodeベースなったことにより,特に日本語のように複数エンコードを持つマルチバイト文字列の扱いに,多少注意が必要になります。ファイルやネットワーク経由の文字列データを元に文字列型データを生成する際には,常にエンコードを意識する必要が出てきます。

たとえば,EUC-JPエンコードで書かれたファイルを開き,読み込んだ結果をそのまま文字列型のデータに代入すると,たいてい例外が発生します。ファイルの内容を文字列に代入する時点で,Pythonのコーデックが文字列の妥当性チェックを行います。このとき,UTF-8として妥当でない文字列があると,エラーが発生するわけです。

このようなことを避けるためには,codecsモジュールのopen()などを使って,読み込み時に明示的にエンコードを指定する必要があります。

>>> import codecs
>>> f=codecs.open('foo_euc.txt')
>>> print(f.read('r', 'euc-jp'))
(ファイルの内容を表示)

8ビットデータ列としてのbytes型

エンコードを明示せず,マルチバイト文字列を8ビットのデータとして扱いたいときには,bytes型を使います。bytes型は2.xまでのstr型とほぼ同じ機能を提供している文字列型です。同時に,bytes型のリテラル表記として「b"~"」が追加されています。

Python 2.xまででは,str型とunicode型を連結することができました。連結をするとunicode型のデータを得ます。連結の過程でstr型からunicode型への暗黙の型変換が行われており,このときエンコードエラーが起こることがありました。暗黙に行われる型変換の最中にエラーがでるというのは,仕様として紛らわしいですし,あまり気持ちの良いものではありません。

Python 3.0では,標準のUnicode文字列と8ビットデータを扱うbytes型がまったく違う型として扱われます。そのため,'abc'+b'abc'のようにしてstr型とbytes型を連結できなくなっています。2つのオブジェクトを連結するためには,enocde()decode()メソッドを使って,明示的に型を合わせる必要があります。

変更可能なbytearray型

Pythonの文字列型は変更不可能(immutable)」と呼ばれています。s[2]='c'のようにして,文字列の要素を直接変更することができません。

Pythonの文字列型は8ビットクリーンなデータをストアできたため,バイナリデータの置き場所として利用されることがありました。また,テキストデータを扱う場合でも,インデックスやスライスを使ってデータを変更できた方が便利な場合があります。このような用途に利用するため,「変更可能(mutable)」なバイト列を扱うためのデータ型としてbytearrayという型が追加されています。

bytearrayにはリテラルはありません。str型やbytes型を元にして生成します。str型からbytearrayを生成するためには,エンコードを指定する必要があります。

>>> ba=bytearray('abcde', 'utf-8')
>>> ba[2]
99
>>> ba[2]=ord('C')
>>> ba
bytearray(b'abCde')
>>> ba[2:4]=b'BCDE'
>>> ba
bytearray(b'abBCDEe')

int型とlong型の統合,割り算に関する変更

Pythonの仕様変更に関する提案を記載したPEPというものがあります。Pyton 3.0では,PEP 237という比較的古いPEPに記載された提案が採用されています。2つの数値型,int型とlong型の統合です。

int型はCのlongに依存した数値型です。long型は後付けでPythonに追加された数値型で,メモリが許す限り大きな値を扱えます。Python 3.0では,2.x世代のlong型に相当する型がint型に置き換わります。これにあわせて,2.x世代で利用されていた「L」を末尾に付けるlong型のリテラル表記は廃止されます。

PEP 237が2001年に書かれていることからもわかるとおり,かなり以前から統合の提案がありました。しかし,後方互換性を崩すという理由のため,ずっと統合が見送られてきたのです。

また,Python 2.xまでは,int型同士の割り算は必ずint型を返していました。結果が小数点を含む数値となった場合は,内輪で一番近い整数を結果としていました。「1/2」の結果は「0」になります。Python 3.0では,int型同士の割り算は必ずfloat型の数値を返します。従来通りint型を得たい場合には//という演算子を使います。

著者プロフィール

柴田淳(しばたあつし)

Webcore株式会社代表取締役。Python,Ploneを使ったCMS/システム構築やコンサルティングが主な業務となっています。「みんなのPython」「TurboGears×Python」などの著書があります。日本Pythonユーザ会のほか,日本PostgreSQLユーザ会でも活動。

URLhttp://coreblog.org/ats/

著書

コメント

コメントの記入