前言 昨天在跟小伙伴聊天,當他談起自己正在做的項目時,一臉愁容。 他吐槽道:“該項目的 Python 代碼庫由多個人共同維護。由於每個人使用的編輯器不同,每個人的編碼風格也不同,最終導致了 代碼的縮進千奇百怪:有縮進 2 個空格的,有縮進 4 個空格的,有縮進 8 個空格,有縮進一個 Tab 的,更 ...
前言
昨天在跟小伙伴聊天,當他談起自己正在做的項目時,一臉愁容。
他吐槽道:“該項目的 Python 代碼庫由多個人共同維護。由於每個人使用的編輯器不同,每個人的編碼風格也不同,最終導致了
代碼的縮進千奇百怪:有縮進 2 個空格的,有縮進 4 個空格的,有縮進 8 個空格,有縮進一個 Tab 的,更有縮進隨機數量空
的。導致代碼的可讀性非常差。“
小伙伴還說:“這種長短不一的代碼看著非常難受,我就手動將它們全部改成標準四空格縮進了。也考慮過使用自動化腳本,但一
時間沒什麼思路,就擱置了。”
這反映出一個問題:不同長度的縮進,雖不影響代碼解釋,但可讀性非常差,一律使用標準的四空格縮進是個不錯的主意。於
是,我便嘗試寫一個簡單的腳本工具,來解決這個實際問題。
經過簡單分析,確定如下思路:
•由於 Python 的縮進是按照層級進行的,只要下一層縮進比上一層更深,且同一層級的所有代碼縮進相同即可;
•可以逐行對源文件進行處理,對每一行源代碼,統計行前空格字元數量,確定該行代碼的縮進層級;
•每嵌套一層縮進,將空格數量增加四位,並記錄當前縮進層級;
•當發現當前行的縮進層級小於上一行代碼,則表示當前行已跳出一層或所層嵌套,對記錄層級的列表由後至前進行搜索,找到當
前行代碼對應的縮進層級;
•對於當前行代碼,根據其縮進層級,對其行首添加相應數量的空格。
為了統計每一行源代碼前的空格數量,我們使用 行的原始長度 - 刪除行左側空白後的長度 表示。
示例代碼如下:
Python學習交流Q群:903971231#### 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])
上面代碼只是一個簡單的做法,當然我們可以根據目錄或者更多規則進行文件格式化,本例僅做拋磚引玉之意。
今天的分享到這裡就結束了,下一章見啦!!!