最近两天要给公司的小朋友写个工具,需要在控制台输出一些信息。 开始以为是一件简单的事情。 但是谁让田老师是处女座呢,追求完美不是。
如果要在终端输出格式的信息,计算字符串的显示宽度就是必要的事情。 但是对与这个看似简单的功能,Python的len()函数并不能有效的解决这个问题,只能自己研究了。 (多么怀念VB里面的LenB()函数啊。)
既然len()函数无法解决中文的显示长度问题。 那么只能使用标准库unicodedata
中的east_asian_width()
函数来解决问题。这个函数可以根据给到的unicode字符的值,判断是半角还是全角。
找了一下中文互联网上的资料,还没有文章把这个问题说透。 所以写成此文记录之。
这里主要要说明3个问题:
East Asian Width
这个概念unicodedata.east_asian_width()
函数的基本使用(不只是中文)East Asian Width
“东亚字符宽度”是 Unicode 标准附件之一。 它定义了East_Asian_Width参考特征,该特征提供有关 Unicode 中每个字符的字符宽度的提示。
East Asian Width
(东亚字符宽度)这个概念被定义是在《Unicode® 标准附录 #11》中。 链接为:UAX #11:东亚宽度 (unicode.org)
对于东亚语言来说,主要是固定间距字体。 要处理的内容包括半角英数字、正常的汉字、半角显示的特殊字符,以及从日语shift-jis编码过来的颜文字等各种特殊字符。
以田老师的项目经验,中文在此方面还算是相对简单的。 中等复杂的是日语,既有类似与中文的“日语汉字”、平假名(あいうえお)、片假名(アイウエオ)、还有小子表示的片假名(アイウエオ)。 当然,最复杂的还要数西里尔语言体系、阿拉伯语、希腊语方面的应用。
Python通过unicodedata.east_asian_width()
通过6种分类,给出每一个unicode字符的宽度。这六种分类分别是:
import unicodedataif __name__ == "__main__":print(unicodedata.east_asian_width('A')) # 全角字母Aprint(unicodedata.east_asian_width('ア')) # 日语半角假名print(unicodedata.east_asian_width('田')) # 汉字‘田’print(unicodedata.east_asian_width('k')) # 英语字母kprint(unicodedata.east_asian_width('Б')) # 西里尔语系,俄语字母Бprint(unicodedata.east_asian_width('ل')) # 阿拉伯语ل
输出结果
D:\Python-grp\miniconda3_data\env\py3.10\python.exe E:\develop\python\pystudy\src\unicode_east_asian_width.py
F
H
W
Na
A
N进程已结束,退出代码0
unicodedata.east_asian_width
常见错误本函数的常见错误,就是输入的是字符串而不是字符。比如:
>>> import unicodedata
>>> unicodedata.east_asian_width('田辛')
Traceback (most recent call last):File "", line 1, in
TypeError: east_asian_width() argument must be a unicode character, not str
>>> unicodedata.east_asian_width('田')
'W'
>>> unicodedata.east_asian_width('辛')
'W'
>>>
def get_east_asian_width_count(text):count = 0for c in text:if unicodedata.east_asian_width(c) in 'FWA':count += 2else:count += 1return count
函数调用
if __name__ == "__main__":print(get_east_asian_width_count('田辛'))print(get_east_asian_width_count('pythonとは?'))print(get_east_asian_width_count('1234567890'))
输出结果
D:\Python-grp\miniconda3_data\env\py3.10\python.exe E:\develop\python\pystudy\src\unicode_east_asian_width.py
4
12
10进程已结束,退出代码0
因为项目经验有限,本文在处理中文,基本日文语言中没有问题。 涉及到俄文、阿拉伯语项目可能还有不足之处。当然UAX #11: East Asian Width (unicode.org)的原始作者小林剣本人也承认这一点。