关于文本输出内容的对齐问题
在Python语言中,对于文本内容,最为简单的对齐方法可以使用两种方式:
第一种是Tab键,即键盘左上角的Tab键,它会自动将下一个输出内容按照定宽整数比的距离来自动设置。即使连续输出多个长度不一的字符串,中间使用Tab键相隔,也会自动形成定宽输出的效果,比如:
print('a\tbb') print('ccc\tdddd')输出为:
a bb
ccc dddd
可以看出默认使用即使前面字符串的长度不一,但是在Tab键后再次输出的内容保持左边上下对齐。
巧妙使用Tab键,可以快速实现简单的对齐效果。如:
for i in range(1, 10): print(i * i, end='\t') if i % 3 == 0: print()输出为:
1 4 9
16 25 36
49 64 81
第二种方法是利用Python自带的字符串格式化方法,做法很多,下面只以format函数为例。
print('{:>4}'.format('1')) print('{:>4}'.format('200'))输出为:
1
200
此时1的前面有三个空格,包括1在内共计4个字符位,1右对齐,这些都是“>4”格式控制的效果。
因此,利用这个方法,我们可以重写刚才的连续整数输出:
for i in range(1, 10): print('{:>4}'.format(i * i), end='') if i % 3 == 0: print()输出为:
1 4 9
16 25 36
49 64 81
但是,仔细的读者可以注意到,此时对于字母和数字效果都比较好,但是如果换成了汉字,情况就变化了:
print('{:>4}'.format('1')) print('{:>4}'.format('汉字'))输出为:
1
汉字
原因很简单,汉字较宽,字母和数字较窄,因此按字符个数来定位,必然会产生宽窄不统一的可能性。甚至即使对于只使用英文字母的输出内容,如果复制到其他文本编辑器中,并使用了不等宽的字体,依然还会出现不对齐的可能。此时并不是代码问题,而是字体问题。可以考虑使用等宽的英文字体,而对于中英文混用输出而言,大部分字体都不会使用相同宽度来显示,因此仍然较难对齐。
更为有效的方法可以考虑两种方法:
一是使用网页表格,比如上述两个数值的上下对齐:
print('<html><table>') print('<tr><td align="right">{}</td></tr>'.format('1')) print('<tr><td align="right">{}</td></tr>'.format('200')) print('</table></html>')输出为:
<html><table>
<tr><td align="right">1</td></tr>
<tr><td align="right">200</td></tr>
</table></html>
复制粘贴到文本文件,并改为HTML扩展名,即可在浏览器中看到上下右对齐。
二是使用第三方对齐模块,比如rich模块,在使用pip安装后,代码修改为:
from nltk.corpus.reader import titles from rich.console import Console from rich.table import Table console = Console() table = Table() table.add_column(justify="right", style="cyan", no_wrap=True) table.add_row(str(1)) table.add_row(str(200)) console.print(table)此时直接输出可能效果不好:
┏━━━━━┓
┃ ┃
┡━━━━━┩
│ 1 │
│ 200 │
└─────┘
此时Windows用户可以打开命令行窗体(CMD),再运行代码,效果可以更好。
最后通过几个练习串一下。
准备将学生课程成绩信息的记录使用数据透视表来展示,比如有:
这是第一个代码,使用了Tab键:
data = {('张三', '语文'): 80, ('张三', '数学'): 94, ('李四', '语文'): 79, ('李四', '英语'): 99, ('王二', '数学'): 81} names = set([unit[0] for unit in data]) courses = set([unit[1] for unit in data]) print('\t'.join(['\t'] + [name for name in names])) for course in courses: print(course, end='\t') for name in names: print(str(data[(name, course)]) + '\t' if (name, course) in data else '\t', end='\t') print()输出为:
王二 李四 张三
数学 81 94
英语 99
语文 79 80
实际你看到的效果可能不好,但是这里效果还行。这是因为字体显示宽度不同而不同,即使是这里,也出现了左右对齐成绩的不统一效果。
再次使用format格式化:
data = {('张三', '语文'): 80, ('张三', '数学'): 94, ('李四', '语文'): 79, ('李四', '英语'): 99, ('王二', '数学'): 81} names = set([unit[0] for unit in data]) courses = set([unit[1] for unit in data]) print(''.join(['{:>8}'.format('')] + ['{:>8}'.format(name) for name in names])) for course in courses: print('{:>8}'.format(course), end='') for name in names: print('{:>8}'.format(data[(name, course)]) if (name, course) in data else '{:>8}'.format(''), end='') print()输出为:
王二 张三 李四
语文 80 79
数学 81 94
英语 99
实际你看到的效果可能较好,但是这里却因为字体显示宽度不同而不同。但是仍然会存在汉字和数字宽度不同的差异。
再次修改下,使用Tab和format综合表达:
data = {('张三', '语文'): 80, ('张三', '数学'): 94, ('李四', '语文'): 79, ('李四', '英语'): 99, ('王二', '数学'): 81} names = set([unit[0] for unit in data]) courses = set([unit[1] for unit in data]) print(''.join(['{:>4}\t'.format('')] + ['{:>4}\t'.format(name) for name in names])) for course in courses: print('{:>4}\t'.format(course), end='') for name in names: print('{:>4}\t'.format(data[(name, course)]) if (name, course) in data else '{:>4}\t'.format(''), end='') print()输出为:
这个实际显示效果是最好的。即使改变课程名称使其长度不一,问题也不大。
最后我们来试试rich模块。
from rich.table import Table from rich.console import Console data = {('张三', '语文'): 80, ('张三', '数学'): 94, ('李四', '语文'): 79, ('李四', '英语'): 99, ('王二', '数学'): 81} names = sorted(set([unit[0] for unit in data])) courses = sorted(set([unit[1] for unit in data])) table = Table(title="处理结果汇总", border_style="green") table.add_column("课程", style="bold", justify="center") for name in names: table.add_column(name, style="bold", justify="right") for course in courses: row = [course] for name in names: score = str(data[(name, course)]) if (name, course) in data else " " row.append(score) table.add_row(*row) console = Console() console.print(table)该代码使用了更为漂亮的颜色格式,需要使用命令行窗体来运行:
