はじめに
忘れてしまいがちな、unicode、文字コードあたりをpythonであれこれする際の基本情報をまとめてみました。
おさらい:n進数
まず、今回のテーマを整理する上で、あれってなりがちなn進数のpythonでの扱い、振舞いについてまとめます。文字コードまわりをあれこれやる際には特に2進数、8進数、16進数というのがよく登場します。
int型 → n進数str型への変換
bin(12) # '0b1100': bin()は数値(int)を、'0b'という接頭辞付きの2進数に変換
hex(12) # '0xc': hex()は数値(int)を、'0x'という接頭辞付きの16進数に変換
n進数str型 → int型への変換
int('0b1100', 2) # 12
int('0xc', 16) # 12
# int('n進数文字列', n)でn進数文字列を数値(int)に変換
pythonではint型が人目に触れる場合、原則として10進数にて表示されます。ただ、入力においては以下のように10進数以外の記述方法も用意されています。
0b1100 # 12, 0b+2進数で2進数表記の数値をint型で宣言
0xc # 12, 0x+16進数で16進数表記の数値をint型で宣言
文字列とUnicodeコードポイントをあれこれやる時
Unicodeは文字コードに関する業界規格ですが、その中でも「符号化文字集合」では、世界中の文字を共通の文字集合として扱うために、各文字に対して番号が割り振られて管理されています。
その世界中の文字を管理するために割り振られた番号を「Unicodeコードポイント」と言います。この「Unicodeコードポイント」は後述するエンコード(UTF-8やShift-jisなど)とは異なるものであることに注意が必要です。
###文字(str)→Unicodeコードポイント(int)への変換
ord('1文字')で文字をUnicodeコードポイントに変換します。
ord("a") # 97
ord("あ") # 12354
# ord("aa") TypeError: ord()は二文字以上の文字列は与えられない
###Unicodeコードポイント(int)→文字(str)への変換
chr(Unicodeコードポイントint)で対応する文字を返します。
chr(97) # 'a'
chr(12354) # 'あ'
###16進数Unicodeコードポイントを文字列として扱うエスケープシーケンス
文字列中の16進数Unicodeコードポイントを文字として扱うエスケープシーケンスとして、\x、\u、\Uが用意されています。それぞれのエスケープシーケンスの後には、2桁、4桁、8桁の16進数で表されたUnicodeコードポイントが続きます。
# 97(aのunicodeコードポイント)は16進数で61
'\x61です' # 'aです'
'\u0061です' # 'aです'
'\U00000061です' # 'aです'
# 12354('あ'のunicodeコードポイント)は16進数で3042
'\u3042です' # 'あです'
'\U00003042です' # 'あです'
#文字とコードをあれこれやる時
文字コードとはコンピュータ上で文字を利用する目的で各文字に割り当てられるバイト表現です。またはバイト表現と文字の対応関係のことを指して文字コードということもあります。
文字コードの代表例としてUTF-8やShift-jisなどがありますが、各文字コードでは「どのような文字集合」を、「何バイト」で表すかが決められています。代表的なものでは、
- asciiは「数字、アルファベット、記号」を「1バイト」で表す
- Shift-jisは「数字、アルファベット、記号に加え日本語」を「1バイトまたは2バイト」で表す
- UTF-8は「Unicodeに含まれるすべての文字」を「1-6バイト」で表す
など。
文字を文字コード(バイト表現)に変換することをエンコード、文字コードを文字に変換することをデコードと言います。
pythonでは、'文字'.encode('文字コード')で対応する文字コードをバイト型で得て、b'文字コード'.decode('文字コード')で対応する文字を得ます。
# ascii
'a'.encode('ascii') # b'a'
'あ'.encode('ascii') # UnicodeEncodeError: 'ascii'は日本語は対象外
b'a'.decode('ascii') # 'a'
# Shift-jis
'a'.encode('shift-jis') # b'a'
'あ'.encode('shift-jis') # b'\x82\xa0'
b'a'.decode('shift-jis') # 'a'
b'\x82\xa0'.decode('shift-jis') # 'あ'
# UTF-8
'a'.encode('utf-8') # b'a'
'あ'.encode('utf-8') # b'\xe3\x81\x82'
b'a'.decode('utf-8') # 'a'
b'\xe3\x81\x82'.decode('utf-8') # 'あ'