一、基本資訊
1、編譯環境、作者等資訊
編譯環境:Pycharm2017、Python3.6
項目名稱:詞頻統計——增強功能
作者: 1613072026:唐順成
1613072027:吳 濤
2、本次作業的位址:
https://edu.cnblogs.com/campus/ntu/Embedded_Application/homework/2088
二、項目分析
Task 1. 接口封裝 —— 将基本功能封裝成(類或獨立子產品)
1.封裝好的fengz.py
import re
from string import punctuation
class wordCount:
def process_file(dst): # 讀檔案到緩沖區
try: # 打開檔案
f = open(dst, 'r') # path為檔案路徑
except IOError as s:
print(s)
return None
try: # 讀檔案到緩沖區
# 如果檔案很大,那麼放到清單裡計算長度的方法将會很慢,是以循環會更好些
count = 0
for count, line in enumerate(f):
count += 1
f.close()
f = open(dst, 'r')
bvffer = f.read()
except:
print('Read File Error!')
return None
f.close()
return bvffer, count
def process_buffer(bvffer): # 處理緩沖區,傳回存放每個單詞頻率的字典if bvffer:
# 下面添加處理緩沖區bvffer代碼,統計每個單詞的頻率,存放在字典word_freq
word_freq = {}
# 用空格代替标點符号,并且去掉大小寫,之後進行正則比對
bvffer = bvffer.replace(punctuation, '').lower().split(' ')
regex_word = "^[a-z]{4}(\w)*"
words = []
for word in bvffer: # 判定是否符合單詞的定義
if re.match(regex_word, word):
words.append(word)
txtWords = open("stopwords.txt", 'r').readlines() # 讀取停詞表檔案
stopWords = [] # 存放停詞表的list
# 讀取文本是readlines是以寫入list要将換行符取代
for i in range(len(txtWords)):
txtWords[i] = txtWords[i].replace('\n', '')
stopWords.append(txtWords[i])
for word in words:
if word not in stopWords: # 當單詞不在停詞表中時,使用正規表達式比對
if word in word_freq.keys():
# 資料字典已經存在該單詞,數量+1
word_freq[word] = word_freq[word] + 1
else:
# 不存在,把單詞存入字典,數量置為1
word_freq[word] = 1
return word_freq, len(words)
def output_result( word_freq):
if word_freq:
sorted_word_freq = sorted(word_freq.items(), key=lambda v: v[1], reverse=True)
for item in sorted_word_freq[:10]: # 輸出 Top n 的單詞
print('<' + str(item[0]) + '>:' + str(item[1]))
return sorted_word_freq
def save_result(self, lines, words_number, sorted_word_freq): # 儲存結果到檔案(result.txt)
try:
result = open("result.txt", "w") # 以寫模式打開,并清空檔案内容
except Exception as e:
result = open("result.txt", "x") # 檔案不存在,建立檔案并打開
# 寫入檔案result.txt
result.write("lines:" + lines + "\n")
result.write("words:" + words_number + "\n")
for item in sorted_word_freq[:self.n]:
item = '<' + str(item[0]) + '>:' + str(item[1]) + '\n'
result.write(item)
print('寫入result.txt檔案已完成!')
result.close()
def print_result(dst):
buffer, lines = wordCount.process_file(dst)
word_freq, words_number = wordCount.process_buffer(buffer)
lines = str(lines)
words_number = str(words_number)
sorted_word_freq=wordCount.output_result(word_freq)
wordCount.save_result( lines, words_number, sorted_word_freq)
2.測試類test.py
import fengz
import argparse
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--file', '-file', type=str, default='Gone_with_the_wind.txt', help="讀取檔案路徑")
args = parser.parse_args() # 将變量以标簽-值的字典形式存入args字典
dst = args.file
fengz.wordCount.print_result(dst) #此處為類的調用
3、測試函數的效果:
(1)測試函數在Pycharm中運作截圖
(2)測試函數在CMD中運作截圖
Task 2. 增加新功能
1.封裝好的fengz.py
import re
from string import punctuation
class wordCount:
def __init__(self, dst, m, n, o): # dst:打開檔案路徑;m:詞組長度;n:輸出的單詞數量;o表示輸出檔案的存儲路徑
self.dst = dst
self.m = m
self.n = n
self.o = o
def process_file(self): # 讀檔案到緩沖區
try: # 打開檔案
f = open(self.dst, 'r') # path為檔案路徑
except IOError as s:
print(s)
return None
try: # 讀檔案到緩沖區
# 如果檔案很大,那麼放到清單裡計算長度的方法将會很慢,是以循環會更好些
count = 0
for count, line in enumerate(f):
count += 1
f.close()
f = open(self.dst, 'r')
bvffer = f.read()
except:
print('Read File Error!')
return None
f.close()
return bvffer, count
def process_buffer(self, bvffer): # 處理緩沖區,傳回存放每個單詞頻率的字典word_freq
if bvffer:
# 下面添加處理緩沖區bvffer代碼,統計每個單詞的頻率,存放在字典word_freq
word_freq = {}
# 用空格代替标點符号,并且去掉大小寫,之後進行正則比對
count = bvffer.replace(punctuation, '').lower().split(' ')
regex = ''
for i in range(self.m):
regex += '[a-z]+'
if i < self.m - 1:
regex += '\s'
result = re.findall(regex, bvffer) # 正則查找詞組
word_freq = {}
for word in result: # 将正則比對的結果進行統計
word_freq[word] = word_freq.get(word, 0) + 1
return word_freq, len(count)
def output_result(self, word_freq):
if word_freq:
sorted_word_freq = sorted(word_freq.items(), key=lambda v: v[1], reverse=True)
for item in sorted_word_freq[:self.n]: # 輸出 Top n 的單詞
print('<' + str(item[0]) + '>:' + str(item[1]))
return sorted_word_freq[:self.n]
def save_result(self, lines, words_number, sorted_word_freq): # 儲存結果到檔案(result.txt)
try:
result = open(self.o, "w") # 以寫模式打開,并清空檔案内容
except Exception as e:
result = open(self.o, "x") # 檔案不存在,建立檔案并打開
# 寫入檔案result.txt
result.write("lines:" + lines + "\n")
result.write("words:" + words_number + "\n")
for item in sorted_word_freq[:self.n]:
item = '<' + str(item[0]) + '>:' + str(item[1]) + '\n'
result.write(item)
print('寫入'+self.o+'檔案已完成!')
result.close()
def print_result(self):
buffer, lines = wordCount.process_file(self)
word_freq, words_number = wordCount.process_buffer(self, buffer)
print('統計詞組長度為:' + str(self.m) + '且詞頻前' + str(self.n) + '的單詞')
lines = str(lines)
words_number = str(words_number)
sorted_word_freq=wordCount.output_result(self, word_freq)
wordCount.save_result(self, lines, words_number, sorted_word_freq)
2、測試類
import fengz
import argparse
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="test example")
parser.add_argument('--i', '-i', type=str, default='Gone_with_the_wind.txt', help="讀取檔案路徑")
parser.add_argument('--m', '-m', type=int, default=2, help="詞組長度")
parser.add_argument('--n', '-n', type=int, default=4, help="輸出前n的單詞/詞組")
parser.add_argument('--o', '-o', type=str, default='result.txt', help="寫入檔案路徑")
args = parser.parse_args() # 将變量以标簽-值的字典形式存入args字典
dst = args.i
m = args.m
n = args.n
o = args.o
obj = fengz.wordCount(dst, m, n, o) # 将參數傳給類
obj.print_result()
3、運作成果截圖:
(1)詞組長度為1,輸出前5詞組
(2)詞組長度為2,輸出前4詞組
(3)詞組長度為3,輸出前5詞組,且指定輸出路徑為re.txt
三、性能分析
(1)使用gprof2dot進行性能分析可視化
四、PSP 表格
1、結對程式設計時間開銷:
PSP2.1 | Personal Software Process Stages | 預估耗時(分鐘) | 實際耗時(分鐘) |
Planning | 計劃 | 30 | 25 |
· Estimate | · 估計這個任務需要多少時間 | 120 | 130 |
Development | 開發 | 160 | 150 |
· Analysis | · 需求分析(含學習新技術) | 60 | 50 |
· Design | · 編寫設計文檔 | ||
· Design Review | · 設計複審 | 35 | |
· Coding Standard | · 代碼規範 | 10 | |
· 具體設計 | 55 | ||
· Coding | · 具體編碼 | 80 | 70 |
· code review | · 代碼複審 | ||
· test | · 測試 | 20 | |
Reporting | 報告 | ||
· Test report | · 測試報告 | ||
· Size measurement | · 計算工作量 | 5 | |
· Postmortem | ·事後總結 | ||
合計 | 675 | 660 |
五、事後分析與總結
(1)針對某個問題的讨論決策過程:
就cmd運作py腳本傳參的問題,我們通過查詢,找到了二種方法,1、
sys.argv;2、
argparse子產品。通過比較我們發現argparse子產品對于傳多個參數而且argparse子產品還包含位置參數,這樣讓處理指令行參數很快捷和友善。
(2)評價對方:
請評價一下你的合作夥伴,又哪些具體的優點和需要改進的地方。 這個部分兩人都要提供自己的看法。
吳濤評價唐順成 :聰明思維靈活,樂于幫助我,促進大家學習進步。程式設計能力強,有發散思維。
唐順成評價吳濤 :樂于學習新知識,但是Python的知識不夠熟練。
(3)評價整個過程:關于結對過程的建議:
(1) 結對程式設計不僅檢驗了程式設計能力,也極高了我們團結合作能力,我們在程式設計過程中互相鼓勵,互相幫助,因為一旦某個功能實作不了,我們會很着急。兩個人可以互相鼓勵,也同時形成一種良性競争,比如這個方法是其中一個人想出來的,另一個人就會去思考有沒有更快的方法。希望有機會可以再次結對程式設計。
(2)建議: 有合作就有競争,互相之間應該,以合作為主,互相學習。
(4)結對程式設計照片:
(5)其他:
不斷的結對合作程式設計,我們配合的越開越默契,這是一個好的結果,希望我們的合作成果越來越好。