web-dev-qa-db-ja.com

Python strとUnicodeタイプ

Python 2.7を使用して、unicodeの代わりにstr型を使用することの利点は、どちらもUnicode文字列を保持できるように見えるためです。エスケープ文字\を使用してunicode文字列にUnicodeコードを設定できること以外に特別な理由はありますか?:

以下を使用してモジュールを実行します。

# -*- coding: utf-8 -*-

a = 'á'
ua = u'á'
print a, ua

結果:á、á

編集:

Pythonシェルを使用した追加テスト:

>>> a = 'á'
>>> a
'\xc3\xa1'
>>> ua = u'á'
>>> ua
u'\xe1'
>>> ua.encode('utf8')
'\xc3\xa1'
>>> ua.encode('latin1')
'\xe1'
>>> ua
u'\xe1'

したがって、unicode文字列はlatin1の代わりにutf-8を使用してエンコードされ、生の文字列はutf-8?を使用してエンコードされます。私は今さらに混乱しています! :S

97
Caumons

unicodeは、textを処理するためのものです。テキストはコードポイントのシーケンスであり、これはは1バイトよりも大きい場合があります。テキストを特定のエンコードでencodedして、テキストを未加工バイト(たとえば、utf-8latin-1...)で表すことができます。 。

unicodeはエンコードされていないことに注意してください! pythonで使用される内部表現は実装の詳細であり、必要なコードポイントを表現できる限り、気にする必要はありません。

反対に、Python 2のstr 2は、bytesの単純なシーケンスです。テキストを表していません!

unicodeは、いくつかのテキストの一般的な表現と考えることができ、さまざまな方法でstrで表される一連のバイナリデータにエンコードできます。

注:Python 3では、unicodestrに名前変更され、プレーンシーケンス用の新しいbytesタイプがあります。バイト

あなたが見ることができるいくつかの違い:

>>> len(u'à')  # a single code point
1
>>> len('à')   # by default utf-8 -> takes two bytes
2
>>> len(u'à'.encode('utf-8'))
2
>>> len(u'à'.encode('latin1'))  # in latin1 it takes one byte
1
>>> print u'à'.encode('utf-8')  # terminal encoding is utf-8
à
>>> print u'à'.encode('latin1') # it cannot understand the latin1 byte
�

strを使用すると、特定のエンコード表現の単一バイトを低レベルで制御できますが、unicodeを使用すると、コードポイントレベルでのみ制御できます。たとえば、次のことができます。

>>> 'àèìòù'
'\xc3\xa0\xc3\xa8\xc3\xac\xc3\xb2\xc3\xb9'
>>> print 'àèìòù'.replace('\xa8', '')
à�ìòù

以前は有効なUTF-8でしたが、もうありません。 Unicode文字列を使用すると、結果の文字列が有効なUnicodeテキストではないような方法で操作することはできません。コードポイントを削除したり、コードポイントを別のコードポイントに置き換えたりすることはできますが、内部表現を台無しにすることはできません。

169
Bakuriu

端末はたまたまUTF-8に設定されています。

aの印刷が機能するという事実は偶然です。端末に未加工のUTF-8バイトを書き込みます。 aは長さtwoの値で、2バイト、16進値C3およびA1を含み、uaはUnicode値ですコードポイントU + 00E1を含む長さone.

この長さの違いは、Unicode値を使用する主な理由の1つです。バイト文字列内のtext文字の数を簡単に測定することはできません。バイト文字列のlen()は、エンコードされた文字数ではなく、使用されたバイト数を示します。

Unicode値を異なる出力エンコーディングにencodeすると、違いがわかります。

>>> a = 'á'
>>> ua = u'á'
>>> ua.encode('utf8')
'\xc3\xa1'
>>> ua.encode('latin1')
'\xe1'
>>> a
'\xc3\xa1'

Unicode標準の最初の256コードポイントはLatin 1標準に一致するため、U + 00E1コードポイントは16進数値E1のバイトとしてLatin 1にエンコードされます。

さらに、Pythonは、ユニコードとバイト文字列の表現でエスケープコードを使用し、印刷できないASCIIは、\x..エスケープ値を使用して表現されます。これが、128〜255のコードポイントを持つUnicode文字列が、Latin 1エンコーディングのようにjustに見える理由です。 U + 00FFを超えるコードポイントを持つユニコード文字列がある場合、異なるエスケープシーケンスが使用され、代わりに\u....が使用され、4桁の16進値が使用されます。

Unicodeとエンコーディングの違いが何であるかをまだ完全には理解していないようです。続行する前に、次の記事を読んでください。

29
Martijn Pieters

ユニコードとエンコーディングはまったく関係のないものです。

Unicode

各文字に数値IDを割り当てます。

  • 0x41→A
  • 0xE1→á
  • 0x414→Д

そのため、UnicodeはAに0x41、áに0xE1、Дに0x414を割り当てます。

私が使用した小さな矢印でも、Unicode番号があり、0x2192です。そして絵文字にもユニコード番号がありますか???? 0x1F602です。

この表 ですべての文字のUnicode番号を検索できます。特に、上記の最初の3文字 here 、矢印 here 、および絵文字 here を見つけることができます。

Unicodeによってすべての文字に割り当てられたこれらの番号は、コードポイントと呼ばれます。

このすべての目的は、各文字を明確に参照する手段を提供することです。たとえば、????について話している場合、「あなたは知っている、涙で笑う絵文字」と言う代わりに、私はただ言うことができますUnicodeコードポイント0x1F602。簡単ですか?

Unicodeコードポイントは通常、先頭にU+を付けてフォーマットし、その後16進数の数値を少なくとも4桁に埋め込むことに注意してください。したがって、上記の例はU + 0041、U + 00E1、U + 0414、U + 2192、U + 1F602になります。

Unicodeコードポイントの範囲はU + 0000〜U + 10FFFFです。それは1,114,112個の数字です。これらの番号のうち2048個が 代理 に使用されているため、1,112,064が残っています。つまり、Unicodeは一意のID(コードポイント)を1,112,064個の個別の文字に割り当てることができます。これらのコードポイントのすべてがまだ文字に割り当てられているわけではなく、Unicodeは継続的に拡張されています(たとえば、新しい絵文字が導入されたとき)。

覚えておくべき重要なことは、すべてのユニコードは、簡単で明確な参照のために、コードポイントと呼ばれる数値IDを各文字に割り当てることです

エンコーディング

文字をビットパターンにマップします。

これらのビットパターンは、コンピューターのメモリまたはディスク上の文字を表すために使用されます。

文字の異なるサブセットをカバーする多くの異なるエンコーディングがあります。英語圏では、最も一般的なエンコードは次のとおりです。

ASCII

128文字 (コードポイントU + 0000からU + 007F)を長さ7のビットパターンにマッピングします。

例:

  • a→1100001(0x61)

この table ですべてのマッピングを確認できます。

ISO 8859-1(Latin-1)

191文字 (コードポイントU + 0020からU + 007EおよびU + 00A0からU + 00FF)を長さ8のビットパターンにマッピングします。

例:

  • a→01100001(0x61)
  • á→11100001(0xE1)

この table ですべてのマッピングを確認できます。

TF-8

1,112,064文字 (既存のすべてのUnicodeコードポイント)を、長さ8、16、24、または32ビット(つまり、1、2、3、または4バイト)のビットパターンにマッピングします。

例:

  • a→01100001(0x61)
  • á→11000011 10100001(0xC3 0xA1)
  • ≠→11100010 10001001 10100000(0xE2 0x89 0xA0)
  • ???? →11110000 10011111 10011000 10000010(0xF0 0x9F 0x98 0x82)

UTF-8が文字をビット文字列にエンコードする方法は、非常によく説明されています here

ユニコードとエンコーディング

上記の例を見ると、Unicodeがどのように役立つかが明らかになります。

たとえば、私がLatin-1であり、áのエンコーディングを説明したい場合、言う必要はありません。

「私はそれをaigu(またはあなたがその上昇バーと呼ぶ)で11100001としてエンコードします。」

しかし、私は言うことができます:

「U + 00E1を11100001としてエンコード」

そして、私がUTF-8である場合、私は言うことができます:

「次に、私はU + 00E1を11000011 10100001としてエンコードします」

そして、私たちがどの性格を意味するかは誰にとっても明白です。

しばしば生じる混乱に

エンコードのビットパターンは、2進数として解釈すると、この文字のUnicodeコードポイントと同じになることがあります。

例えば:

  • ASCIIはaを1100001としてエンコードします。これは16進数0x61およびUnicodeコードとして解釈できますaのポイントはU + 0061です。
  • Latin-1はáを11100001としてエンコードします。これは16進数0xE1として解釈できます。 áのUnicodeコードポイントはU + 00E1です。

もちろん、これは便宜上このように配置されています。しかし、あなたはそれを純粋な偶然の一致として見るべきです。メモリ内の文字を表すために使用されるビットパターンは、この文字のUnicodeコードポイントとは一切関係ありません。

11100001のようなビット文字列を2進数として解釈する必要があると言う人さえいません。 Latin-1が文字áをエンコードするために使用するビットのシーケンスとして見てください。

質問に戻る

Pythonインタープリターが使用するエンコードは、UTF-8です。

あなたの例で起こっていることは次のとおりです。

例1

以下は、文字áをUTF-8でエンコードします。これにより、ビット文字列11000011 10100001が変数aに保存されます。

>>> a = 'á'

aの値を見ると、そのコンテンツ11000011 10100001は16進数0xC3 0xA1としてフォーマットされ、'\xc3\xa1'として出力されます。

>>> a
'\xc3\xa1'

例2

以下は、áのUnicodeコードポイント(U + 00E1)を変数uaに保存します(PythonがコードポイントU + 00E1を表すために内部で使用するデータ形式はわかりません)メモリ内で、それは私たちにとって重要ではありません):

>>> ua = u'á'

uaの値を見ると、Pythonは、コードポイントU + 00E1が含まれていることを示します。

>>> ua
u'\xe1'

例3

次は、UnicodeコードポイントU + 00E1(文字áを表す)をUTF-8でエンコードします。これにより、ビットパターン11000011 10100001が生成されます。再び、出力では、このビットパターンは16進数0xC3 0xA1として表されます。

>>> ua.encode('utf-8')
'\xc3\xa1'

例4

以下は、UnicodeコードポイントU + 00E1(文字áを表す)をLatin-1でエンコードし、ビットパターン11100001になります。出力の場合、このビットパターンは16進数0xE1として表され、これはby偶然は初期コードポイントU + 00E1と同じです:

>>> ua.encode('latin1')
'\xe1'

UnicodeオブジェクトuaとLatin-1エンコーディングとの間に関係はありません。 áのコードポイントがU + 00E1であり、áのLatin-1エンコードが0xE1であること(エンコードのビットパターンを2進数として解釈する場合)は、まったくの偶然です。

25
weibeld

AをUnicodeとして定義すると、文字aとáは等しくなります。それ以外の場合は、áは2つの文字としてカウントされます。 len(a)とlen(au)を試してください。それに加えて、他の環境で作業するときはエンコードが必要になる場合があります。たとえば、md5を使用する場合、aとuaに異なる値を取得します

2
Ali Rasim Kocal