軟工作業 5:結對專案之詞頻統計——增強功能
軟工作業5:詞頻統計——增強功能
一、基本資訊
1.1 編譯環境、專案名稱、作者
1 #編譯環境:python3,Geany 2 #專案名稱:結對專案詞之詞頻統計—增強功能 3 #作者:1613072037 張銘銳 4 # 1613072036 譚琪
1.2專案地址
- 本次作業地址: https://edu.cnblogs.com/campus/ntu/Embedded_Application/homework/2088
- 專案git地址: https://gitee.com/ntucs/PairProg/tree/SE036_037
二、專案分析
-
程式執行模組(方法、函式)介紹
Task 1. 介面封裝 —— 將基本功能封裝成(類或獨立模組)
將基本功能:統計文字總詞數,統計文字最多的十個單詞及其詞頻這兩個方法封裝在類wordclass中
1 #coding=gbk 2 import re 3 4 class wordclass: 5 6 def process_file(dst): # 讀取檔案 7 countline = len(open(dst, 'r').readlines()) # 文字的行數countline8 with open(dst) as f: 9 bvffer = f.read() 10 f.close() 11 return bvffer 12 13 def process_buffer(bvffer): 14 if bvffer: 15 for ch in '“‘!;:,.?”': 16 bvffer = bvffer.lower().replace(ch, " ") 17 wordmatch = "^[a-z]{4}(\w)*" #正則表示式至少以4個英文字母開頭,跟上字母數字符號,單詞以分隔符分割,不區分大小寫 18 # 將文字內容都改為小寫且去除文字中的中英文標點符號 19 words = [] 20 for i in range(len(bvffer)): 21 word = re.match(wordmatch, bvffer[i]) # 匹配list中的元素 22 if word: # 匹配成功,加入words 23 words.append(word.group()) 24 # strip()刪除空白符(包括'/n', '/r','/t');split()以空格分割字串 25 words = bvffer.strip().split() 26 word_freq = {} 27 for word in words: # 對words進行統計 28 word_freq[word] = word_freq.get(word, 0) + 1 29 return word_freq, len(words) 30 31 def output_result(word_freq): 32 if word_freq: 33 sorted_word_freq = sorted(word_freq.items(), key=lambda v: v[1], reverse=True) 34 for item in sorted_word_freq[:10]: # 輸出 Top 10 的單詞 35 print("單詞:%s 頻數:%d " % (item[0], item[1])) 36 return sorted_word_freq[:10] 37 38 def result(dst): 39 buffer = wordclass.process_file(dst) 40 word_freq, countwords = wordclass.process_buffer(buffer) 41 print('文字總單詞數:' + str(countwords)) 42 print('文字中最多的10個單詞及其詞頻') 43 wordclass.output_result(word_freq)
編寫一個test.py,通過import argparse模組,可以在cmd命令列中測試上述的封裝類
1 #coding=gbk 2 import WordCount 3 import argparse 4 if __name__ == '__main__': 5 parser = argparse.ArgumentParser(description="your script description") # description引數可以用於插入描述指令碼用途的資訊,可以為空 6 parser.add_argument('--file', '-file', type=str, default='D:/桌面/python_work/SE037/Gone_with_the_wind.txt', help="讀取檔案路徑")#default屬性是預設值,當引數輸入錯誤時使用預設引數 type後表示引數的型別 7 args = parser.parse_args() # 將變數以標籤-值的字典形式存入args字典 8 path = args.file #通過鍵值對形式取值 9 WordCount.wordclass.result(path) #此處為類的呼叫
下圖為統計所用的文字Gone_with_the_wind_txt
下圖為在IDE環境下執行截圖
下圖為在命令列傳參截圖
Task 2. 增加新功能
- 片語統計:能統計資料夾中指定長度的片語的詞頻
- 自定義輸出:能輸出使用者指定的前n多的單詞與其數量
封裝類wordclass的程式碼:
1 #coding=gbk 2 import re 3 class wordclass: 4 def __init__(self,path,m,n,o): #類wordclass的構造方法 path為檔案路徑 m為片語長度 n為輸出單詞數量 o為生成的result檔案儲存路徑 5 self.path=path 6 self.m=m 7 self.n=n 8 self.o=o 9 10 def process_file(self): 11 countline = len(open(self.path, 'r').readlines()) # countline為文字行數 12 with open(self.path) as f: 13 bvffer = f.read() 14 f.close() 15 return bvffer, countline 16 17 18 def process_buffer(self,bvffer): # 處理緩衝區,返回存放每個單詞頻率的字典word_freq 19 if bvffer: 20 word_freq = {} 21 words = [] 22 for ch in '“‘!;:,.?”': 23 bvffer = bvffer.lower().replace(ch, " ") 24 words = bvffer.strip().split() 25 match='[a-z]+' 26 for i in range((self.m)-1): 27 match+='\s[a-z]+' #m長度片語的正則表示式 28 result = re.findall(match, bvffer) # 正則查詢片語 29 for word in result: 30 word_freq[word]=word_freq.get(word,0)+1 31 return word_freq,len(words) 32 33 34 35 def output_result(self,word_freq): 36 if word_freq: 37 sorted_word_freq = sorted(word_freq.items(), key=lambda v: v[1], reverse=True) 38 for item in sorted_word_freq[:self.n]: # 輸出 Top n 的單詞 39 print("單詞:%s 頻數:%d " % (item[0], item[1])) 40 return sorted_word_freq[:self.n] 41 42 def result(self): 43 print('需查詢的文字路徑:'+str(self.path)) 44 print('需查詢的片語長度:'+str(self.m)) 45 print('需查詢的詞頻Top:'+str(self.n)) 46 buffer,countline=wordclass.process_file(self) 47 word_freq,lenwords=wordclass.process_buffer(self,buffer) 48 clines= 'lines:' + str(countline) 49 cwords = 'words:' + str(lenwords) 50 print(clines) 51 print(cwords) 52 items =wordclass.output_result(self,word_freq) 53 with open(self.o, 'w') as w: 54 w.write(clines+'\n') 55 w.write(cwords+'\n') 56 for item in items: # 格式化 57 item = '<' + str(item[0]) + '>:' + str(item[1]) + '\n' 58 w.write(item) 59 print('將該檔案寫入路徑為:'+self.o) 60 w.close() 61 62 63 64 65 66 #if __name__ == '__main__': 67 # obj = wordclass('D:/桌面/python_work/Gone_with_the_wind.txt', 2, 3, 'D:/桌面/python_work/SE037/result.txt') 68 # obj.result() 69 70 71 72 73
import argparse模組進行命令列傳參測試程式碼:
1 #coding=gbk 2 import wordclass 3 import argparse 4 import cProfile 5 import pstats 6 7 def main(): 8 parser = argparse.ArgumentParser(description="your script description") # 建立一個解析物件 description引數可以用於插入描述指令碼用途的資訊,可以為空 9 parser.add_argument('--i', '-i', type=str,required=True,help="讀取檔案路徑")#新增--i標籤,標籤別名可以為-i,required=Truerequired表示---引數是必需的,並且型別為str,輸入別的型別會報錯。 10 parser.add_argument('--m', '-m', type=int,required=True,help="輸出的單詞數量") 11 parser.add_argument('--n', '-n', type=int,required=True,help="輸出的單詞數量") 12 parser.add_argument('--o', '-o', type=str,required=True,help="讀取檔案路徑") 13 args = parser.parse_args() # 進行解析 將變數以標籤-值的字典形式存入args字典 14 path = args.i 15 m = args.m 16 n = args.n 17 o = args.o 18 obj = WordCount.wordclass(path, m, n, o) 19 obj.result() 20 if __name__ == '__main__': 21 cProfile.run("main()", "pstats_result") 22 # 把分析結果儲存到檔案中,不過內容可讀性差...需要呼叫pstats模組分析結果 23 p = pstats.Stats("pstats_result") # 建立Stats物件 24 p.strip_dirs().sort_stats("call").print_stats() # 按照呼叫的次數排序 25 p.strip_dirs().sort_stats("cumulative").print_stats() # 按執行時間次數排序
執行成果圖:
三、效能分析
本次實驗在作業4基礎上進行,在時間、空間複雜度方面差不多,所以執行很流暢。
1.根據呼叫次數分析
2.根據執行時間分析
效能圖表:
四、PSP 表格
五、事後分析與總結
1.簡述結對程式設計時,針對某個問題的討論決策過程
我們在網上查找了python命令列傳參的方式,瞭解到傳遞引數有三種方法:1、引數通過sys.argv傳遞,它的型別是一個list型別,其中的元素為字串。2、通過getopt模組解析Python傳入的引數,它能解析帶'-'和'--'格式的引數。它的函式原型為:getopt.getopt(args, options[, long_options])。3、使用argparse模組解析命令列引數。通過我和譚琪的討論,我們選擇了argparse模組來傳參,因為argparse是一個可以自動生成幫助資訊和錯誤資訊的模組,有利於命令列傳參的除錯分析。
2.評價對方:請評價一下你的合作伙伴,又哪些具體的優點和需要改進的地方。 這個部分兩人都要提供自己的看法。
譚琪評價張銘銳:張銘銳同學在程式設計方面能力很強,在python語言方面很熟練,也很有自己的程式設計想法。需要改進的地方:在編碼過程中需要能夠靈活變通。
張銘銳評價譚琪:譚同學做專案態度很認真,學習能力也很強,我們一開始對python命令列傳參不是很瞭解,他通過學習csdn中的相關帖子教程後掌握了這些方法。需要改進的地方:雖然python基礎還不錯,但還需要學習python深層次的知識。
3.評價整個過程:關於結對過程的建議
結對程式設計需要雙方不斷提出自己的想法並加以結合,耐心理解對方的思路。每人負責相應的模組,但也要融會對方的程序,相互補充和學習。在解決問題的過程中,我們相互啟發和糾正,對於有爭議的問題也是通過實踐來印證。通過此次的結對程式設計,我們體會到合作的重要性以及不理解對方時的艱難,使我們對合作開發有了一定的理解和基礎。
4.結對程式設計照片
5.其他
經過這兩次的合作程式設計,我們雙方的程式設計能力都有提高。在合作的過程中,我們互相學習、幫助,一起解決問題,這兩次的合作對我們非常有意義。