兼容等价
具有相同抽象内容但外观可能不同的两个字符序列,比规范等价更宽泛,例如fi ≈ fi,² ≈ 2。
What Is Compatibility Equivalence?
Two Unicode strings are compatibility equivalent if they represent semantically similar content but may differ in appearance or formatting. Compatibility equivalence is weaker than canonical equivalence: canonically equivalent strings are always compatibility equivalent, but not vice versa.
Common compatibility equivalences include:
- The ligature fi (U+FB01, fi LIGATURE) ≈ fi (f + i separately)
- The superscript ² (U+00B2) ≈ 2 (U+0032)
- The fullwidth A (U+FF21) ≈ A (U+0041)
- The fraction ½ (U+00BD) in NFKD → 1 ⁄ 2 (sequence of three characters)
- The circled digit ① (U+2460) ≈ 1 (U+0031)
Compatibility Normalization Forms
| Form | Description |
|---|---|
| NFKD | Apply compatibility decomposition; apply canonical ordering |
| NFKC | Apply NFKD, then canonically compose |
import unicodedata
examples = [
("\uFB01", "fi ligature"), # fi
("\u00B2", "superscript 2"), # ²
("\uFF21", "fullwidth A"), # A
("\u2460", "circled digit 1"), # ①
("\u00BD", "vulgar fraction 1/2"), # ½
]
for char, label in examples:
nfc = unicodedata.normalize("NFC", char)
nfkc = unicodedata.normalize("NFKC", char)
nfd = unicodedata.normalize("NFD", char)
nfkd = unicodedata.normalize("NFKD", char)
print(f" {char} ({label})")
print(f" NFC len={len(nfc)} NFKC={nfkc!r} len={len(nfkc)}")
print(f" NFD len={len(nfd)} NFKD={[f'U+{ord(c):04X}' for c in nfkd]}")
# fi NFC len=1 NFKC='fi' len=2
# ² NFC len=1 NFKC='2' len=1
# A NFC len=1 NFKC='A' len=1
# ① NFC len=1 NFKC='1' len=1
When to Use NFKC vs NFC
Use NFC when you want to preserve formatting distinctions: a superscript 2 and a plain 2 are different in a math formula. Use NFKC when you want semantic comparison, ignoring presentational variants: a search engine should return results for "fi" when the user types "file". Python uses NFKC for identifier normalization (PEP 3131), so file and file are the same identifier in Python 3.
Caution: NFKC is lossy. Applying it to 2² produces 22, discarding the superscript meaning. Never apply NFKC to content where formatting carries semantic information.
Quick Facts
| Property | Value |
|---|---|
| Concept | Compatibility equivalence |
| Normalization forms | NFKD, NFKC |
| Python function | unicodedata.normalize("NFKC", s) / "NFKD" |
| Lossy? | Yes — formatting distinctions are discarded |
| Python identifier normalization | NFKC (PEP 3131) |
| Search engine use | NFKC for case-folded token normalization |
| Spec reference | Unicode Standard Annex #15 (UAX #15) |
相关术语
字符属性 中的更多内容
字符首次被分配时所在的Unicode版本,有助于判断各系统和软件版本的字符支持情况。
Unicode property (UAX#11) classifying characters as Narrow, Wide, Fullwidth, Halfwidth, Ambiguous, or …
Unicode property controlling how Arabic and Syriac characters connect to adjacent characters. …
Unicode property listing all scripts that use a character, broader than the …
将每个码位归入30个类别(Lu、Ll、Nd、So等)之一的分类体系,分为7大类:字母、标记、数字、标点、符号、分隔符和其他。
将字符映射为其组成部分的过程。规范分解保留语义(é → e + ◌́),兼容分解可能改变语义(fi → fi)。
命名的连续码位范围(如基本拉丁文 = U+0000–U+007F)。Unicode 16.0定义了336个区块,每个码位恰好属于一个区块。
决定字符在双向文本中(LTR、RTL、弱、中性)行为方式的属性,由Unicode双向算法用于确定显示顺序。
由于稳定性策略规定Unicode名称不可更改,因此提供字符的备用名称,用于更正、缩写和别名。
将字符在大写、小写和标题大小写之间转换的规则,可能因区域设置而异(土耳其语I问题),也存在一对多映射(ß → SS)。