1. 程式人生 > >軟工作業 5:結對專案之詞頻統計——增強功能

軟工作業 5:結對專案之詞頻統計——增強功能

軟工作業5:詞頻統計——增強功能


 

一、基本資訊

      1.1 編譯環境、專案名稱、作者  

1 #編譯環境:python3,Geany
2 #專案名稱:結對專案詞之詞頻統計—增強功能
3 #作者:1613072037 張銘銳
4 #         1613072036 譚琪

   1.2專案地址

二、專案分析

  •  程式執行模組(方法、函式)介紹    

    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())  # 文字的行數countline
8 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.其他

    經過這兩次的合作程式設計,我們雙方的程式設計能力都有提高。在合作的過程中,我們互相學習、幫助,一起解決問題,這兩次的合作對我們非常有意義。