python でA-Zみたいに 「ひらがな」をコードポイントで扱う。
tl;dr
>>> [ chr( i+ 0x3042) for i in range(0,85)] ['あ', 'ぃ', 'い', 'ぅ', 'う', 'ぇ', 'え', 'ぉ', 'お', 'か', 'が', 'き', 'ぎ', 'く', 'ぐ', 'け', 'げ', 'こ', 'ご', 'さ', 'ざ', 'し', 'じ', 'す', 'ず', 'せ', 'ぜ', 'そ', 'ぞ', 'た', 'だ', 'ち', 'ぢ', 'っ', 'つ', 'づ', 'て', 'で', 'と', 'ど', 'な', 'に', 'ぬ', 'ね', 'の', 'は', 'ば', 'ぱ', 'ひ', 'び', 'ぴ', 'ふ', 'ぶ', 'ぷ', 'へ', 'べ', 'ぺ', 'ほ', 'ぼ', 'ぽ', 'ま', 'み', 'む', 'め', 'も', 'ゃ', 'や', 'ゅ', 'ゆ', 'ょ', 'よ', 'ら', 'り', 'る', 'れ', 'ろ', 'ゎ', 'わ', 'ゐ', 'ゑ', 'を', 'ん', 'ゔ', 'ゕ', 'ゖ']
解説
chr ( 0x3042 )
これは、以下と同じ
'\u3042'
\u でユニコードにコードポイントであることを示している。
'\u3042'を示したときに、Pythonで内部エンコーディングにデコードされ文字列として格納されている。
文字符号化方式UTF-8/UTF-16でエンコードすると、次のようなバイト列になる。
>>> '\u3042'.encode('utf-8') b'\xe3\x81\x82' >>> '\u3042'.encode('utf-16') b'\xff\xfeB0'
ちなみに、内部エンコーディングは次のように確認できる(いまはUTF-8固定かな?たしか)
import sys; sys.getdefaultencoding()
得られたバイト列を、文字列にする
>>> b'\xe3\x81\x82'.decode() 'あ'
ちなみに b'\xxxx' はバイト列であることを示す b です。
UTF-16のバイト列をそのままデコードしてもエラーになります。
>>> b'\xff\xfeB0'.decode() Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte
内部エンコーディングがUTF-8(デフォルト)なので、UTF-16をUTF-8としてデコードしようとしてエラーですね。
>>> b'\xff\xfeB0'.decode('utf16') 'あ'
これで、バイト列がUTF-16の符号化として扱われて、デコードされ、Unicodeのコードポイントを得ることが出来て、内部エンコーディング(この場合UTF-8)にデコードされ出力された。
ユニコードのコードポイントを連番で扱う。
あ=0x3042 であることを利用して連番「ひらがな」を作ってみる。
>>> [chr(0x3042+i) for i in range(0,10)] ['あ', 'ぃ', 'い', 'ぅ', 'う', 'ぇ', 'え', 'ぉ', 'お', 'か']
逆に、「あいうえお」をすべてユニコードのコードポイントにしてみる
>>> [ (ord(i)) for i in "あいうえお"] [12354, 12356, 12358, 12360, 12362]
見やすいように16進数 Hexにする
>>> [ hex(ord(i)) for i in "あいうえお"] ['0x3042', '0x3044', '0x3046', '0x3048', '0x304a']
まとめ
chr でユニコードのコードポイント(数字)から、文字へ
>>> chr( 0x3042 ) 'あ' >>> chr( 0x3042 + 1 ) 'ぃ'
ord で、文字を数字(int)へ。hex で16進数表記へ
>>> ord('あ') 12354 >>> hex(ord('あ')) '0x3042'
補足
ユニコード(Unicode)のコードポイントは、文字符号の変換表(数字→文字)であり、utf-8 や utf-16 はその変換した数字をバイナリとしてどうやって保存するかになる。
ユニコードでは、あ=0x3042 である。これはUTF-8でもUTF-16 でも変わらない。ただし、この0x304 をどうやって0/1に落とし込むかで表現方法は変わる。