Unicode 文字の名前を取得する
unicodedata.name() を使用する。
>>> import unicodedata
>>> unicodedata.name('s')
'LATIN SMALL LETTER S'
>>> unicodedata.name('す')
'HIRAGANA LETTER SU'
>>> unicodedata.name('🍣')
'SUSHI'
>>> unicodedata.name('🍣🍣')
TypeError: name() argument 1 must be a unicode character, not str
名前から Unicode 文字を取得する
unicodedata.lookup() を使用する。
>>> import unicodedata
>>> unicodedata.lookup('LATIN SMALL LETTER S')
's'
>>> unicodedata.lookup('HIRAGANA LETTER SU')
'す'
>>> unicodedata.lookup('SUSHI')
'🍣'
>>> unicodedata.lookup('SUSI')
KeyError: "undefined character name 'SUSI'"
また \N{名前}
というエスケープシーケンスを使用して Unicode 文字を指定することもできる。
>>> '\N{SUSHI}'
'🍣'
>>> '\N{SUSI}'
SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 0-7: unknown Unicode character name
Unicode 文字のエスケープシーケンスを取得する
str.encode() を使用する。第 1 引数には unicode-escape
を指定する。
>>> 's'.encode('unicode-escape')
b's'
>>> 'す'.encode('unicode-escape')
b'\\u3059'
>>> '🍣'.encode('unicode-escape')
b'\\U0001f363'
返り値は bytes 型である。ここでエスケープシーケンスについて補足説明する。
\u について
\u3059
のように \u
の後ろに 4 個の 16 進数が続くエスケープシーケンスは、基本多言語面 のいずれかに含まれる文字に該当する。最初の 2 桁が面番号を、後半の 2 桁がその面の中でのインデックスを表す。
\U について
\U0001f363
のように \U
の後ろに 8 個の 16 進数が続くエスケープシーケンスは、基本多言語面より上位の面に位置する文字に該当する。なお左端の数字は必ず 0 である。
文字列の len について
>>> type('🍣')
<class 'str'>
>>> len('🍣')
1
>>> len('\U0001f363')
1
>>> len('寿司')
2
Unicode 文字列の長さは文字数を表す。
対して str.encode() の返り値は bytes 型なので、長さはバイト数を表す。
>>> import binascii
>>> encoded = '🍣'.encode('unicode-escape')
>>> encoded
b'\\U0001f363'
>>> type(encoded)
<class 'bytes'>
>>> len(encoded)
10
>>> binascii.b2a_hex(encoded)
b'5c553030303166333633' # 16 進数に変換するとたしかに 10 バイト
>>> '🍣'.encode('UTF-8')
b'\xf0\x9f\x8d\xa3' # 4 バイト
>>> len('🍣'.encode('UTF-8'))
4
Unicode 正規化
任意の形式で 正規化 するには unicodedata.normalize() を使用する。第 1 引数に正規化形式を指定する。
>>> import unicodedata
>>> po = 'ポ'
>>> po_nfc = unicodedata.normalize('NFC', po)
>>> po_nfc
'ポ'
>>> po_nfd = unicodedata.normalize('NFD', po)
>>> po_nfd
'ポ'
>>> po_nfc == po_nfd
False
>>> len(po_nfc)
1
>>> len(po_nfd)
2
>>> unicodedata.normalize('NFD', 'ポ') == unicodedata.normalize('NFKD', 'ポ')
True
>>> unicodedata.normalize('NFC', 'ポ') == unicodedata.normalize('NFKC', 'ポ')
True
>>> unicodedata.decomposition('ポ') # decomposition() は分解マッピングを返す。
'30DB 309A'
>>> 'ポ' == unicodedata.normalize('NFC', '\u30DB\u309A')
True
参考
-
入門 Python 3
- 「7.1.1 Unicode」
- Unicodeの特殊な文字 “結合文字列”