这里写自定义目录标题
str.format() 输出时使中英文按1:2对齐
分析
两个背景知识
format
函数会调用对象的__format__
方法- python 计算字符串的长度时,中文计算出来也是1
解决思路
- 对需要format对齐字符串时在对象外层再包含一层自定义str类,以实现对
__format__
函数的修改 - 想对齐中英文字符,计算出一个字符串中含有多少中文字符或者说计算出每个中英文字符在屏幕显示时所占有的宽度,计算出实际宽度后,令要对齐的字符串中
<5s
5-(实际宽度-len(str)) 来弥补中文问宽度的差距,之后即正常格式化即可
代码
import re
class __MyStr__():
def __init__(self, s) -> None:
self.buff = ''+s
def __str__(self):
return self.buff.__str__()
def __len__(self):
return self.buff.__len__()
def __add__(self, s):
return __MyStr__(self.buff.__add__(s))
def get_real_width(self):
widths = [(126, 1), (159, 0), (687, 1), (710, 0), (711, 1), (727, 0), (733, 1), (879, 0),
(1154, 1), (1161, 0), (4347, 1), (4447, 2), (7467, 1), (7521, 0), (8369, 1), (8426, 0), (9000, 1), (9002, 2),
(11021, 1), (12350, 2), (12351, 1), (12438, 2), (12442, 0), (19893, 2), (19967, 1), (55203, 2), (63743, 1), (64106, 2),
(65039, 1), (65059, 0), (65131, 2), (65279, 1), (65376, 2), (65500, 1), (65510, 2), (120831, 1), (262141, 2), (1114109, 1),
(0xffffffffffffffffffffffffffffffff, 1)]
length = 0
for c in self.buff:
o = ord(c)
if o == 0xe or o == 0xf:
continue
for num, wid in widths:
if o <= num:
length += wid
break
return length
def __format__(self, __format_spec: str) -> str:
# *<4 *>5 *^5
# *<4s *>5s *^5s
# 4 4s
format_spec = __format_spec
format_len = int(re.findall('.*?[<^>]?([\d+]+)s?', format_spec)[0])
format_len -= self.get_real_width()-len(self.buff)
format_spec = re.sub('.*?[<^>]?([\d+]+)s?', str(format_len), format_spec)
return self.buff.__format__(format_spec)
zw = '你好,123'
el = 'english-'
print('\n中英文无法对齐')
print('{0:15s} | '.format(zw))
print('{0:15s} | '.format(el))
print('\n中英文1:2对齐')
print('{0:15s} | '.format(__MyStr__(zw)))
print('{0:15s} | '.format(__MyStr__(el)))