マイクロレベルの変更と 2to3 では適切に対処できない最大の問題は、デフォルトの文字列型がバイトから Unicode に変更されたことです。
コードでエンコーディングとバイト I/O を処理する必要がある場合は、正しく変換するために大量の手作業が必要になります。これにより、バイトでなければならないものがバイトのままになり、適切な段階で適切にデコードされます。一部の文字列メソッド (特にformat()
) とライブラリ呼び出しには Unicode 文字列が必要であることがわかります。そのため、文字列が実際には単なるバイトであっても、文字列を Unicode として使用するためだけに追加のデコード/エンコード サイクルが必要になる場合があります。
これは、一部の Python 標準ライブラリ モジュールがバイト/ユニコード/エンコーディングの問題に適切に注意を払わずに 2to3 を使用して大まかに変換されているという事実によって助けられていません。これの一部は取り除かれていますが、少なくとも Python 3.0 から 3.2 までは、バイト エンコーディングについて知る必要がある urllib、email、wsgiref などのパッケージからの紛らわしい、潜在的にバグのある動作に直面するでしょう。
文字列リテラルを記述するたびに注意することで、問題を改善できます。u''
本質的に文字ベースのものには文字列を使用b''
し、実際にはバイトであるすべてのものには文字列を''
使用し、重要でない場合やライブラリ呼び出しの文字列使用要件に一致させる必要がある場合は「デフォルト文字列」タイプに使用します。
残念ながら、b''
構文は Python 2.6 でのみ導入されたため、これを行うと以前のバージョンのユーザーが切断されます。
イータ:
違いは何ですか?
なんてこった。良い...
1 バイトは 0 ~ 255 の範囲の値を含み、バイナリ データ (画像の内容など) またはテキストの負荷を表す場合があります。文字をそれらのバイトに挿入します。これらの「エンコーディング」標準のほとんどは、通常の「ASCII」文字セットを同じ方法でバイト 0 ~ 127 にマップするため、Python 2 で ASCII のみのテキスト処理にバイト文字列を使用することは一般的に安全です。
バイト文字列で ASCII セット以外の文字を使用したい場合、問題が発生します。これは、各エンコーディングが異なる文字セットを残りのバイト値 128 ~ 255 にマップし、ほとんどのエンコーディングがすべての文字列をマップできないためです。可能な文字からバイト。これは、あるロケールから別のロケールの Windows アプリにファイルをロードすると、すべてのアクセント付き文字またはラテン文字以外の文字が間違った文字に変更されて、判読不能な混乱が生じるという、すべての問題の原因です。(別名「モジバケ」。)
各文字を格納するために複数のバイトを使用して、使用可能なスペースにより多くの文字を収めようとする「マルチバイト」エンコーディングもあります。非常に多くの漢字があるため、これらは東アジアのロケール用に導入されました。しかし、すべての文字に対応できる、より優れた設計の最新のマルチバイト エンコーディングである UTF-8 もあります。
マルチバイト エンコーディングでバイト文字列を処理している場合は、UTF-8 が非常に広く使用されているため、今日ではおそらくそうなるでしょう。実際、最新のアプリケーションでは他のエンコーディングを使用すべきではありません。そうすると、使用しているエンコーディングを追跡するだけでなく、さらに多くの問題が発生します。len()
文字単位の長さではなく、バイト単位の長さを示します。バイトのインデックス作成と変更を開始すると、マルチバイトシーケンスが2つに分割され、無効なシーケンスが生成され、一般的にすべてが混乱する可能性が非常に高くなります.
このため、Python 1.6 以降にはネイティブの Unicode 文字列 (綴りはu'something'
) があり、文字列の各単位はバイトではなく文字です。len()
それらをスライスし、置き換え、正規表現することができ、常に適切に動作します。u
テキスト処理タスクの場合、それらは間違いなく優れています。これが、Python 3 がそれらをデフォルトの文字列型にする理由です ( の前に a を付ける必要はありません''
)。
問題は、Windows 以外の OS のファイル名、HTTP、SMTP など、多くの既存のインターフェイスが主にバイトベースであり、エンコーディングを別の方法で指定していることです。そのため、バイトを必要とするコンポーネントを扱うときは、Unicode 文字列をバイトに正しくエンコードするように注意する必要があります。Python 3 では、以前は必要がなかったいくつかの場所で明示的にエンコードする必要があります。
Unicode 文字列が内部的にユニットごとに「2 バイト」のストレージを使用するのは、内部実装の詳細です。そのストレージを見ることは決してありません。バイト単位で考えるべきではありません。作業しているユニットは、Python がメモリ内でどのように表現するかに関係なく、概念的には文字です。
...余談:
これは正しくありません。Windows ビルドのような Python の「狭いビルド」では、Unicode 文字列の各単位は技術的には文字ではなく、UTF-16 の「コード単位」です。0x0000 ~ 0xFFFF の Basic Multilingual Plane の文字については、違いはわかりませんが、この 16 ビット範囲外の文字、つまり「アストラル プレーン」の文字を使用している場合は、 1 つではなく 2 つのユニットであり、繰り返しますが、スライスするときにキャラクターを分割するリスクがあります。
これはかなり悪いことであり、Unicode が 65,000 文字の制限を超える前に、Windows (および Java などの他のもの) がメモリ内ストレージ メカニズムとして UTF-16 に落ち着いたために発生しました。ただし、これらの拡張文字を使用することはまだかなりまれであり、Windows の誰もが多くのアプリケーションで拡張文字を使用することに慣れているため、重要ではない可能性があります。
「ワイド ビルド」では、Unicode 文字列は実際の文字の「コード ポイント」単位で構成されるため、BMP の外側にある拡張文字も一貫して簡単に処理できます。これの代償は効率です。各文字列ユニットはメモリ内の 4 バイトのストレージを占有します。