軟工作業3:詞頻統計
一、案例程序分析
1.1、編譯環境
pycharm2017、python3.6
1.2、讀文件到緩沖區(process_file(dst))
1 def process_file(dst): # 讀文件到緩沖區 2 try: # 打開文件 3 f = open(dst, ‘r‘) # dst為文本的目錄路徑 4 except IOError as s: 5 print(s) 6 return None 7 try: # 讀文件到緩沖區 8 bvffer = f.read()9 except: 10 print(‘Read File Error!‘) 11 return None 12 f.close() 13 return bvffer
1.3、處理緩沖區,返回存有詞頻數據的字典(process_buffer(bvffer))
1 def process_buffer(bvffer): 2 if bvffer: 3 word_freq = {} # 下面添加處理緩沖區 bvffer代碼,統計每個單詞的頻率,存放在字典word_freq 4 forch in ‘“‘!;,.?”‘: # 將文本內容都改為小寫且除去文本中的中英文標點符號 5 bvffer = bvffer.lower().replace(ch, " ") 6 words = bvffer.strip().split() 7 # strip()刪除空白符(包括‘/n‘, ‘/r‘,‘/t‘);split()以空格分割字符串 8 for word in words: 9 word_freq[word] = word_freq.get(word, 0) + 1 10 returnword_freq
1.4、輸出詞頻前十的單詞(output_result(word_freq))
1 def output_result(word_freq): 2 if word_freq: 3 # 根據v[1]即詞頻數量排序 4 sorted_word_freq = sorted(word_freq.items(), key=lambda v: v[1], reverse=True) 5 for item in sorted_word_freq[:10]: # 輸出 Top 10 的單詞 6 print("詞:%-5s 頻:%-4d " % (item[0], item[1]))
1.5、主函數對之前的函數進行整合(main())
1 if __name__ == "__main__": 2 dst = ‘src/Gone_with_the_wind.txt‘ # 《飄》文件的路徑 3 bvffer = process_file(dst) 4 word_freq = process_buffer(bvffer) 5 output_result(word_freq)
1.6、性能分析
(參考:https://www.cnblogs.com/btchenguang/archive/2012/02/03/2337112.html)
為了方便測試,將原來的運行詞頻的代碼寫在main函數中。
1 def main(): 2 dst = ‘src/Gone_with_the_wind.txt‘ # 《飄》文件的路徑 3 bvffer = process_file(dst) 4 word_freq = process_buffer(bvffer) 5 output_result(word_freq)
主函數入口改為性能分析的代碼。
1 if __name__ == "__main__": 2 cProfile.run("main()", "result") 3 # 把分析結果保存到文件中,不過內容可讀性差...需要調用pstats模塊分析結果 4 p = pstats.Stats("result") # 創建Stats對象 5 p.strip_dirs().sort_stats("call").print_stats() # 按照調用的次數排序 6 p.strip_dirs().sort_stats("cumulative").print_stats() # 按執行時間次數排序 7 # 根據上面2行代碼的結果發現函數process_buffer最耗時間 8 p.print_callees("process_buffer") # 查看process_buffer()函數中調用了哪些函數
二、python代碼風格說明
就塊註釋和行註釋而言:“最需要寫註釋的是代碼中那些技巧性的部分. 如果你在下次 代碼審查的時候必須解釋一下, 那麽你應該現在就給它寫註釋. 對於復雜的操作, 應該在其操作開始前寫上若幹行註釋. 對於不是一目了然的代碼, 應在其行尾添加註釋.”
# 編譯環境:Pycharm2017、Python3.6 # 項目名稱:詞頻統計和性能分析 # 作者:高昶 # 最後修改:2018/9/28 f = open(dst, ‘r‘) # dst為文本的目錄路徑
三、程序運行命令、運行結果截圖
《飄》 文本文件的詞頻統計運行截圖
四、性能分析結果及改進
4.1、總運行時間:
4.2、執行次數最多的部分代碼(篇幅有限,截取部分)
即 word_freq[word] = word_freq.get(word, 0) + 1執行的次數最多
1 word_freq[word] = word_freq.get(word, 0) + 1
4.3、執行時間最多的部分代碼
4.4、根據4.2和4.3的結果發現函數 process_buffer()耗時占比最大,所以查看process_buffer()函數中 調用了哪些函數
4.5、改進
改進可以從二個方面入手,(1)減少耗時;(2)減少調用次數;但是發現其中調用最多的{method‘get‘ of ‘dict‘ objects}可以理解為是對文本中的詞的遍歷, 詞頻算法就是對文本的詞遍歷,所以該方面不好修改。所以可以從減少耗時入手。
可以將如下代碼:
1 for ch in ‘“‘!;,.?”‘: # 將文本內容都改為小寫且除去文本中的中英文標點符號 2 bvffer = bvffer.lower().replace(ch, " ")
改為:(即將bvffer.lower()放在for循環外,我個人理解:設改文本有N個單詞,前者的復雜度為O(N*N),後者復雜度為O(2N))
1 bvffer = bvffer.lower() # 將文本內容都改為小寫 2 for ch in ‘“‘!;,.?”‘: # 將文本內容都改為小寫且除去文本中的中英文標點符號 3 bvffer = bvffer.replace(ch, " ")
修改前後的對比,發現後者比前者快0.2秒左右。(圖一是修改前,圖二是修改後)
圖 一
圖 二
軟工作業3:詞頻統計