前言
昨天在跟小伙伴聊天,当他谈起自己正在做的项目时,一脸愁容。
他吐槽道:“该项目的 Python 代码库由多个人共同维护。由于每个人使用的编辑器不同,每个人的编码风格也不同,最终导致了
代码的缩进千奇百怪:有缩进 2 个空格的,有缩进 4 个空格的,有缩进 8 个空格,有缩进一个 Tab 的,更有缩进随机数量空
的。导致代码的可读性非常差。“
小伙伴还说:“这种长短不一的代码看着非常难受,我就手动将它们全部改成标准四空格缩进了。也考虑过使用自动化脚本,但一
时间没什么思路,就搁置了。”
这反映出一个问题:不同长度的缩进,虽不影响代码解释,但可读性非常差,一律使用标准的四空格缩进是个不错的主意。于
是,我便尝试写一个简单的脚本工具,来解决这个实际问题。
经过简单分析,确定如下思路:
•由于 Python 的缩进是按照层级进行的,只要下一层缩进比上一层更深,且同一层级的所有代码缩进相同即可;
•可以逐行对源文件进行处理,对每一行源代码,统计行前空格字符数量,确定该行代码的缩进层级;
•每嵌套一层缩进,将空格数量增加四位,并记录当前缩进层级;
•当发现当前行的缩进层级小于上一行代码,则表示当前行已跳出一层或所层嵌套,对记录层级的列表由后至前进行搜索,找到当
前行代码对应的缩进层级;
•对于当前行代码,根据其缩进层级,对其行首添加相应数量的空格。
为了统计每一行源代码前的空格数量,我们使用 行的原始长度 - 删除行左侧空白后的长度 表示。
示例代码如下:
Python学习交流Q群:906715085####
1file_input = 'source.py' # file to format
2file_output = 'dest.py' # formated file
3
4fin = open(file_input, 'r')
5fout = open(file_output, 'w')
6
7space = 0
8indent_lists = [0]
9
10for line in fin:
11 # blank line just output
12 if len(line.lstrip()) == 0:
13 fout.write(line)
14 continue
15 # calc curret indent
16 indent = len(line) - len(line.lstrip())
17 # inc space when bigger indent
18 if indent > indent_lists[-1]:
19 indent_lists.append(indent)
20 space = space + 4
21 # dec space when smaller indent
22 while indent < indent_lists[-1]:
23 indent_lists.pop()
24 space = space - 4
25 # format the line
26 line = ' ' * space + line.lstrip()
27 fout.write(line)
28
29fin.close()
30fout.close()
下面我们进行简单的测试。
待格式化的源文件:
1#!/usr/bin/python
2# -*- coding: UTF-8 -*-
3
4for num in range(1, 10):
5 if num % 2 == 0:
6 print(str(num) + ' is even')
7 else:
8 print(str(num) + ' is odd')
可以看到:line5 缩进了 2 个空格,line6 缩进了 8 个空格,line8缩进了 4 个空格。看起来非常杂乱。
使用本脚本格式化后的源文件:
1#!/usr/bin/python
2# -*- coding: UTF-8 -*-
3
4for num in range(1, 10):
5 if num % 2 == 0:
6 print(str(num) + ' is even')
7 else:
8 print(str(num) + ' is odd')
可以看到,执行脚本后,所有的缩进都变成了 4 个空格。舒服了…
随后小伙伴又提出:这个脚本每次只能处理一个文件,能不能批量处理呢?当然可以啦!只要对本脚本进行简单的封装,即可实
现多文件、多目录处理啦:
1def format_file(file_input, file_output):
2 fin = open(file_input, 'r')
3 fout = open(file_output, 'w')
4
5 space = 0
6 indent_lists = [0]
7
8 for line in fin:
9 # blank line just output
10 if len(line.lstrip()) == 0:
11 fout.write(line)
12 continue
13 # calc curret indent
14 indent = len(line) - len(line.lstrip())
15 # inc space when bigger indent
16 if indent > indent_lists[-1]:
17 indent_lists.append(indent)
18 space = space + 4
19 # dec space when smaller indent
20 while indent < indent_lists[-1]:
21 indent_lists.pop()
22 space = space - 4
23 # format the line
24 line = ' ' * space + line.lstrip()
25 fout.write(line)
26
27 fin.close()
28 fout.close()
29
30files_to_format = 3
31file_input_lists = ['1.py', '2.py', '3.py'] # file lists to format
32file_output_lists = ['11.py', '22.py', '33.py'] # formated file lists
33
34for i in range(files_to_format):
35 format_file(file_input_lists[i], file_output_lists[i])
上面代码只是一个简单的做法,当然我们可以根据目录或者更多规则进行文件格式化,本例仅做抛砖引玉之意。
今天的分享到这里就结束了,下一章见啦!!!