Python, web, Algorithm 技術的なメモ

技術的なメモを書いていきます.pythonistaを目指しています.

文字コードとの戦い (2) Unicode,エンコード,utf-8とは?

Python 2.xを使っている限り,文字コードとの戦いは避けられない. 今回は,文字コードについて調べたので,基礎的な事を備忘録としてまとめておく.

Python2.xでは何も指定しない限り,つまりデフォルトでは, 文字列はstrオブジェクトとして認識され,エンコーディングする際はASCIIが指定される.

エンコーディングを理解する上で,ユニコードの説明が書かせないためユニコードの説明を行う. 下図にユニコードとバイト列(数値の列)の関係を示す. まず,理解しておきたいのはUnicodeユニコード)とはUnify codeである, つまりコードを1つにするという意味である.あらゆる文字列を1つのコードで表現出来るようにしたコードである.

例えば,shift-jisエンコードされた文字列(strオブジェクト)をutf-8エンコードした文字列にしたいときは,一度ユニコードに直してからutf-8に変換する必要がある.

また,エンコードとはユニコードをバイト列に変換する事を示し,下図の例では, utf-8エンコードするとバイト列は'\xe3\x81\x84'になり,shift-jisエンコードすると'\x82\xa0'のバイト列で表現できる.

f:id:samuraiT:20131028204243p:plain

まだ理解するのが難しいかもしれないので,実際の例を見てみよう.

例1

*この例ではIPythonの命令を一部利用している IPythonにはobject?とするとobjecttypeなどの情報を表示する便利な機能がある. 今回はその機能を利用している.In[n] はn回めに行われたinputを表しており, Out[n]はoutputである.

In [66]: uni = u'あ'    #ユニコードで`あ`を表現

In [66]: uni
Out[66]: u'\u3042' #ユニコードのバイト列

In [67]: uni?
Type:       unicode
Length:     1

この例では,の前にuを加えユニコードで表現し,uniに代入した. また,uniunicodeオブジェクトである.strオブジェクトではない.

例2

次に,先程のユニコード文字を格納したuniutf-8エンコードすると以下のようになる.

In [127]: uni
Out[127]: u'\u3042'

In [130]: after_encoding = uni.encode('utf-8')

In [131]: after_encoding 
Out[131]: '\xe3\x81\x82'

In [132]: after_encoding?
Type:       str
String Form:あ
Length:     3

エンコードする事により'\xe3\x81\x82'のようなバイト列が得られる. また,これはstrオブジェクトであり,私の環境ではと出力される.

例3

続いて,ユニコード文字を格納したunishift-jisエンコードする.

In [133]: shift_jis_encoding = uni.encode('shift-jis')

In [134]: shift_jis_encoding 
Out[134]: '\x82\xa0'

In [135]: shift_jis_encoding?
Type:       str
String Form:�� #私の環境では??となる
Length:     2

ユニコードshift-jisエンコードすることにより,バイト列'\x82\xa0'が得られ, これもstrオブジェクトである.しかし,私の環境ではshift-jisエンコードされた文字列を 確認する事ができない.なぜなら,私の標準出力ではshift-jisエンコードには対応していないからだ.私の標準出力の設定をShift-jisとすればと出力されるだろう.

まとめ

今回,shift-jisエンコードされた文字を確認できなかったのは,私が使用している環境では,出力先(標準出力)がutf-8しかサポートしていなかったためである.もし,shift-jisエンコードをサポートしている場合はが表示され,utf-8エンコードされた文字は別の文字で表現されるだろう.例えば??など(確認していないため正確にはわからない)

また,ユニコードにすることでマルチバイト文字列を様々な関数に適応することができる. 例えば,今回の例ではunicodeを表現した時のみlength = 1と適切に関数が 適応されている.このようにユニコードにすることで様々な関数への適応,様々な文字コードエンコードすることが可能となる.出力以外の文字をユニコードにすることで,様々な文字コードへのエンコーディングが用意になることから,出力の時にだけエンコードするのが良いと思う.

参考文献