字元與整數代碼點(Code Point)互轉是文字處理基礎。Python 2/3 在此處有顯著差異。本文釐清 ord/chr/unichr 行為邊界,並提供批次轉換實用模式。
| 函數 | Python 版本 | 輸入 | 輸出 | 適用範圍 |
|---|---|---|---|---|
ord(c) | 2/3 | 長度 1 字串 | 整數代碼點 | 全 Unicode (0 ~ 0x10FFFF) |
chr(i) | 3 | 整數 0 ~ 0x10FFFF | 字串 (長度 1) | 全 Unicode |
chr(i) | 2 | 整數 0 ~ 255 | 位元組字串 | 僅 ASCII/擴展 ASCII |
unichr(i) | 2 | 整數 0 ~ 0x10FFFF | Unicode 字串 | 全 Unicode |
str(i) | 2/3 | 任意物件 | 字串表達 | 非字元轉換 |
# ASCII 範圍
print(ord('A')) # 65
print(chr(65)) # 'A' (Py3) / 'A' (Py2)
# Unicode 範圍
print(ord('哈')) # 21704 (0x54C8)
print(chr(21704)) # '哈' (Py3)
# Py2: unichr(21704) -> u'哈'
# 邊界測試
print(chr(0x10FFFF)) # 最大合法代碼點
# chr(0x110000) -> ValueError
print(chr(97)) # 'a' (代碼點 -> 字元)
print(str(97)) # '97' (整數 -> 字串表達)
# 字串 -> 代碼點列表
text = 'Python'
codes = [ord(c) for c in text]
print(codes) # [80, 121, 116, 104, 111, 110]
# 代碼點列表 -> 字串
text2 = ''.join(chr(c) for c in codes)
print(text2) # 'Python'
# 使用 map(函數式風格)
codes = list(map(ord, '哈囉'))
print(codes) # [21704, 21705]
text3 = ''.join(map(chr, range(21704, 21707)))
print(text3) # '哈囉嘩'
import unicodedata
# 合成字元 vs 分解字元
s1 = 'é' # U+00E9 (單一代碼點)
s2 = 'e\u0301' # e + 重音符 (兩個代碼點)
print(ord(s1)) # 233
print([ord(c) for c in s2]) # [101, 769]
# 正規化為 NFC (合成形式)
print(unicodedata.normalize('NFC', s2) == s1) # True
# 正確計算「使用者感知字元數」(字素叢集)
import regex # pip install regex
len(regex.findall(r'\X', s2)) # 1
chr 只支援 0-255,Unicode 用 unichr;字串預設 bytes。chr 支援全 Unicode;unichr 移除;字串預設 Unicode。try: unichr except NameError: unichr = chr掌握代碼點互轉,是處理編碼、加密、字型、自然語言的入門鑰匙。