軟工作業2-詞頻統計

来源:https://www.cnblogs.com/wsywsy123/archive/2019/04/14/10707947.html
-Advertisement-
Play Games

軟工作業2 ——實現一個能夠對文本文件中的單詞的詞頻進行統計的控制台程式 1.Github地址: https://github.com/wangshiyaoyao/WordCont 2.PSP表格 PSP2.1 Personal Software Process Stages 預估耗時(分鐘) 實際 ...


軟工作業2

                                                                                ——實現一個能夠對文本文件中的單詞的詞頻進行統計的控制台程式

1.Github地址:

https://github.com/wangshiyaoyao/WordCont

2.PSP表格

PSP2.1

Personal Software Process Stages

預估耗時(分鐘)

實際耗時(分鐘)

Planning

計劃

   

· Estimate

· 估計這個任務需要多少時間

   

Development

開發

   

· Analysis

· 需求分析 (包括學習新技術)

120

360

· Design Spec

· 生成設計文檔

30

30

· Design Review

· 設計覆審

10

10

· Coding Standard

· 代碼規範 (為目前的開發制定合適的規範)

20

20

· Design

· 具體設計

30

30

· Coding

· 具體編碼

120

120

· Code Review

· 代碼覆審

20

40

· Test

· 測試(自我測試,修改代碼,提交修改)

120

300

Reporting

報告

   

· Test Repor

· 測試報告

60

60

· Size Measurement

· 計算工作量

30

30

· Postmortem & Process Improvement Plan

· 事後總結, 並提出過程改進計劃

30

30

 

合計

590

1030

 

3.需求分析

    實現一個能夠對文本文件中的單詞的詞頻進行統計的控制台程式

       功能實現:

       讀取文件

              獲取文件名

              判斷獲取參數是否正確

              判斷文件是否可讀取,否則報錯處理

       根據文件內容進行分析處理

              統計字元個數

              統計有效行數

              統計詞頻

                     詞頻排序,獲取前十

              統計單詞數

       輸出結果

測試用例:

       創建臨時文件

根據一定規則隨機生成內容

記錄生成內容的有效單詞等各種你參數

                     功能測試

              測試統計字元個數

              測試統計有效行數

              測試統計詞頻

              測試統計單詞數

難點:

       單詞匹配,使用正則表達式,學習其語法

       測試套件的使用

       隨機生成文件內容

代碼規範:

       使用python3.7+ pycharm

       單函數單功能

       添加註釋,提高代碼可讀性

       代碼符合pep8規範,使用pylint進行檢查

       使用Profile進行性能檢測

4.代碼設計

   Get_argv函數:獲取並返回程式執行第一個參數,進行參數個數校驗,有誤返回空字元串,

   Main函數:接受一個文件名字元串,輸出分析結果,無返回

        創建文件分析實例,進行分析,獲取輸出結果,進行輸出

   _file_check函數:文件名檢查,若不能打開並讀取,進行報錯,程式異常退出

   FileHandler類:

       __init__:初始化用於保存結果的各類變數,接受文件名,調用函數進行檢查,調用分析函數進行分析

       _analysis:打開文件,讀取內容,對讀取內容調用歐冠具體函數進行分析,最後對詞頻排序

       _chars_analysis:字元統計,使用len函數

       _line_analysis:有效行統計,使用strip函數判斷有效行

       _word_analysis:詞頻統計,調用單詞檢查函數獲取合法單詞,使用lower函數統一為小寫

       _word_sum:單詞數統計,調用單詞檢查函數獲取合法單詞

       _sort_conatiner:詞頻結果排序,取前十結果

       介面函數:

       chars:獲取字元統計結果

       cotainer:獲取詞頻前10統計結果

   lines:獲取有效行統計結果

   words:獲取單詞數目統計結果

   _word_check_in_line:函數:獲取字元串中合法單詞,使用正則表達式匹配

 

   單元測試:

       創建臨時文件

     根據一定規則隨機生成內容

    記錄生成內容的有效單詞等各種你參數

       通過正則表達式反向匹配生成任意符合測試要求的內容,文件大小可控,覆蓋較全面。

                     功能測試

              測試統計字元個數

              測試統計有效行數

              測試統計詞頻

              測試統計單詞數

5.關鍵功能實現

文件檢查:

1 def _file_check(filename):
2     """判斷參數是一個可讀文件,否則報錯"""
3     try:
4         fd = open(filename)
5         fd.close()
6     except IOError:
7         logging.error("Invalid argument.\nNeed a readable file.")
8         sys.exit(1)

 

對文件進行嘗試可讀打開,失敗進行報錯,並異常退出

類初始化:

def __init__(self, filename, encoding='utf-8'):
    self._chars = 0                                               # 統計ascii
    self._container = {}                                          # 統計詞頻
    self._lines = 0                                               # 統計行數
    self._words = 0                                               # 統計單詞數
    self._sorted_container = []                                   # 輸出詞頻
    _file_check(filename)
    self._analysis(filename, encoding)

 

使用字典進行詞頻統計,避免重覆

文件預設使用utf-8打開

詞頻統計:

1 def _word_analysis(self, line):
2     """統計詞頻"""
3     for word_match in _word_check_in_line(line):
4         word = word_match.lower()
5         self._container[word] = self._container.get(word, 0) + 1

 

使用字典的get函數對初次添加做特殊初始化

合法單詞檢查:

1 def _word_check_in_line(line):
2     """單詞匹配"""
3     pattern = r'(?<![a-zA-Z0-9])([a-zA-Z][0-9a-zA-Z]*)'
4     result = re.findall(pattern, line)
5     # logging.debug('word check in line result:%s', result)
6     return result

 

       使用正則進行檢查

       匹配字元開頭後跟任意長度字元或數字,單詞前一字元不為字母數字

       使用findall函數獲取所有合法單詞,以列表存儲

 

詞頻結果處理:

1 def _sort_container(self):
2     """詞頻結果排序,獲取前10結果"""
3     self._sorted_container = sorted(self._container.items(), key=lambda x: (-x[1], x[0]))[:10]

 

       使用sorted函數對字典進行排序

    參數:key=lambda x: (-x[1], x[0])

           表示排序依據,先根據字典值大->小排序,後根據字典鍵按字典序排序

           [:10]:表示取前十個結果

 

生成用於測試的臨時文件:

 1 def touch_test_file(line_num, word_num):
 2     """創建測試文件,隨機生成字元,用於測試"""
 3 
 4     _x = Xeger()
 5     words = lambda: _x.xeger(r'[a-zA-Z][a-zA-Z0-9]*')       # 隨機生成有效單詞
 6     non_word = lambda: _x.xeger(r'\d[a-zA-Z0-9]*')          # 隨機生成開頭為數字的單詞
 7     separator = lambda: _x.xeger(r'[^a-zA-Z0-9\n\r]')       # 隨機生成非字母數字回車換行符的字元
 8     space = lambda: _x.xeger(r'\n[\s]*\n')                  # 隨機生成回車空白字元回車
 9 
10     # 統計生成的文件中字元、單詞、有效行、詞頻
11     result = {'chars': 0, 'words': word_num * line_num, 'lines': line_num, 'container': {}}
12 
13     # 創建文件,隨機生成字元
14     fd = open(temp_file, 'w')
15     for line in range(line_num):
16         for i in range(word_num):
17             word = words()
18             chars = word + separator() + non_word() + separator()
19             result['chars'] += len(chars)
20             result['container'][word.lower()] = result['container'].get(word.lower(), 0) + 1
21             fd.write(chars)
22         chars = space()
23         result['chars'] += len(chars)
24         fd.write(chars)
25     fd.close()
26 
27     # 獲取排序後的詞頻結果
28     sort_result = sorted(result['container'].items(), key=lambda x: (-x[1], x[0]))[:10]
29     result['container'] = sort_result
30     return result

使用第三方庫xeger,反向生成符合正則的任意字元串

創建好要生成的合法非法單詞,字元,空白字元等

創建臨時文件,隨機生成字元串寫入

將結果返回

6.代碼風格說明

  Unused variable 'line' (unused-variable):未使用的參數:for迴圈中,使用_代替

  Trailing newlines (trailing-newlines):文件末尾多餘空行,刪除

7.運行結果

 

測試運行:

 

8.性能分析結果及改進

使用cProfile

         182480 function calls (182313 primitive calls) in 0.207 seconds

 

   Ordered by: internal time

 

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)

     7382    0.057    0.000    0.057    0.000 {method 'findall' of 're.Pattern' objects}

        1    0.049    0.049    0.057    0.057 {built-in method builtins.sorted}

     3691    0.025    0.000    0.074    0.000 WordCont.py:64(_word_analysis)

        1    0.010    0.010    0.190    0.190 WordCont.py:74(_analysis)

    40049    0.008    0.000    0.008    0.000 {method 'get' of 'dict' objects}

    33382    0.008    0.000    0.008    0.000 WordCont.py:87(<lambda>)

    40006    0.006    0.000    0.006    0.000 {method 'lower' of 'str' objects}

     7385    0.005    0.000    0.010    0.000 re.py:271(_compile)

       13    0.004    0.000    0.004    0.000 {built-in method builtins.print}

     7382    0.004    0.000    0.068    0.000 re.py:215(findall)

     3691    0.004    0.000    0.040    0.000 WordCont.py:70(_word_sum)

     7382    0.004    0.000    0.072    0.000 WordCont.py:25(_word_check_in_line)

 

        1    0.003    0.003    0.060    0.060 WordCont.py:85(_sort_container)

     7681    0.002    0.000    0.002    0.000 {built-in method builtins.isinstance}

     3691    0.002    0.000    0.003    0.000 WordCont.py:59(_line_analysis)

       57    0.002    0.000    0.002    0.000 {built-in method nt.stat}

     3691    0.002    0.000    0.002    0.000 WordCont.py:55(_chars_analysis)

       10    0.002    0.000    0.002    0.000 {built-in method marshal.loads}

     3691    0.001    0.000    0.001    0.000 {method 'strip' of 'str' objects}

       10    0.001    0.000    0.001    0.000 {method 'read' of '_io.FileIO' objects}

7762/7732    0.001    0.000    0.001    0.000 {built-in method builtins.len}

       45    0.001    0.000    0.002    0.000 {built-in method builtins.__build_class__}

        1    0.001    0.001    0.207    0.207 WordCont.py:8(<module>)

           19/4    0.001    0.000    0.002    0.000 sre_parse.py:475(_parse)

…… …… ……

       Findall函數耗時最多,sorted其次,內建函數暫無法優化。

 

按執行次數分析:

         182480 function calls (182313 primitive calls) in 0.216 seconds

 

   Ordered by: call count

 

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)

    40049    0.009    0.000    0.009    0.000 {method 'get' of 'dict' objects}

    40006    0.006    0.000    0.006    0.000 {method 'lower' of 'str' objects}

    33382    0.008    0.000    0.008    0.000 WordCont.py:87(<lambda>)

7762/7732    0.001    0.000    0.001    0.000 {built-in method builtins.len}

     7681    0.003    0.000    0.003    0.000 {built-in method builtins.isinstance}

     7385    0.006    0.000    0.011    0.000 re.py:271(_compile)

     7382    0.004    0.000    0.076    0.000 WordCont.py:25(_word_check_in_line)

 

     7382    0.004    0.000    0.072    0.000 re.py:215(findall)

     7382    0.058    0.000    0.058    0.000 {method 'findall' of 're.Pattern' objects}

     3691    0.002    0.000    0.003    0.000 WordCont.py:55(_chars_analysis)

     3691    0.002    0.000    0.003    0.000 WordCont.py:59(_line_analysis)

     3691    0.025    0.000    0.078    0.000 WordCont.py:64(_word_analysis)

     3691    0.004    0.000    0.042    0.000 WordCont.py:70(_word_sum)

     3691    0.001    0.000    0.001    0.000 {method 'strip' of 'str' objects}

      411    0.000    0.000    0.000    0.000 sre_parse.py:233(__next)

       執行次數最多代碼:get函數,lower函數

 

按函數運行時間分析:

         182480 function calls (182313 primitive calls) in 0.201 seconds

 

   Ordered by: cumulative time

 

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)

     12/1    0.000    0.000    0.201    0.201 {built-in method builtins.exec}

        1    0.001    0.001    0.201    0.201 WordCont.py:8(<module>)

        1    0.000    0.000    0.190    0.190 WordCont.py:115(main)

        1    0.000    0.000    0.188    0.188 WordCont.py:46(__init__)

        1    0.010    0.010    0.187    0.187 WordCont.py:74(_analysis)

     3691    0.023    0.000    0.073    0.000 WordCont.py:64(_word_analysis)

     7382    0.004    0.000    0.070    0.000 WordCont.py:25(_word_check_in_line)

 

     7382    0.004    0.000    0.066    0.000 re.py:215(findall)

        1    0.003    0.003    0.060    0.060 WordCont.py:85(_sort_container)

        1    0.050    0.050    0.057    0.057 {built-in method builtins.sorted}

     7382    0.055    0.000    0.055    0.000 {method 'findall' of 're.Pattern' objects}

     3691    0.004    0.000    0.039    0.000 WordCont.py:70(_word_sum)

     14/3    0.000    0.000    0.012    0.004 <frozen importlib._bootstrap>:978(_find_and_load)

     14/3    0.000    0.000    0.011    0.004 <frozen importlib._bootstrap>:948(_find_and_load_unlocked)

     14/3    0.000    0.000    0.011    0.004 <frozen importlib._bootstrap>:663(_load_unlocked)

     10/3    0.000    0.000    0.010    0.003 <frozen importlib._bootstrap_external>:722(exec_module)

     18/3    0.000    0.000    0.010    0.003 <frozen importlib._bootstrap>:211(_call_with_frames_removed)

     7385    0.005    0.000    0.009    0.000 re.py:271(_compile)

       運行時間最多函數main函數,__init__初始化函數。

附:

ncalls:表示函數調用的次數;
tottime:表示指定函數的總的運行時間,除掉函數中調用子函數的運行時間;
percall:(第一個percall)等於 tottime/ncalls;
cumtime:表示該函數及其所有子函數的調用運行的時間,即函數開始調用到返回的時間;
percall:(第二個percall)即函數運行一次的平均時間,等於 cumtime/ncalls;
filename:lineno(function):每個函數調用的具體信息;

性能分析圖:

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 9、REINDEX API Reindex要求為源索引中的所有文檔啟用_source。 不會配置目標索引,不會複製源索引的設置。你需要在reindex之前先指定 ,分片數量,副本數量等選項。 最常用的一種方式是複製一個索引。下例會將twitter索引中的文檔複製到new_twitter索引中: 返回 ...
  • 我們今天繼續學習一下Numpy庫 接著前面幾次講的,Numpy中還有一些標準運算 exp表示求e的冪次方,比如上面看到的,e的0次方為1,e的2次方,2.7幾,以此類推 我們可以看到,exp就是求e的多少次方 而sqrt則表示根號,也就是進行開方運算 我們可以得到,0的開方為0,1 的開方為1,2的 ...
  • 靜態語言(C/C++、Java);腳本語言(python、JavaScript、PHP) IPO(Input、Process、Output) #:python中的註釋符號;‘’‘ ’‘’:多行註釋 python的35個保留字 數據類型:字元串、整數、浮點數、列表 整數類型:10011101 字元串類 ...
  • 上次使用了BeautifulSoup庫爬取電影排行榜,爬取相對來說有點麻煩,爬取的速度也較慢。本次使用的lxml庫,我個人是最喜歡的,爬取的語法很簡單,爬取速度也快。 本次爬取的豆瓣書籍排行榜的首頁地址是: https://www.douban.com/doulist/1264675/?start= ...
  • 新聞 "Hedgehog新站點" "Bolero 0.4發佈,增加遠程認證" "FsToolkit.ErrorHandling與Cvdm.ErrorHandling合併了" "F 里的3D圖形編程與游戲開發" "有趣的3D——瀏覽器里F 3D繪製" "F CNTK:變分自動編碼器例子——從2D隱空間 ...
  • 閱讀目錄 一、迭代器 1、迭代的概念 #迭代器即迭代的工具,那什麼是迭代呢? #迭代是一個重覆的過程,每次重覆即一次迭代,並且每次迭代的結果都是下一次迭代的初始值 代碼如下: 2、為何要用迭代器?什麼是可迭代對象?什麼是迭代器對象? 3、迭代器對象的使用 4、for迴圈 5、迭代器的優缺點 ...
  • 8、Bulk API 可以把多個 或`delete bulk API`中執行。這樣可以極大地提高索引速度。 API使用如下的JSON結構: 註意,最後一行數據必須要以 結尾。發送請求時,Content Type 標頭應設置為 application /x ndjson。 可以是 ,`create d ...
  • 一、引言 有了自動配置,springboot使web開發變得簡單,這個在springboot之旅中的第一篇中就有體現,實際的開發中當然不會這麼簡單,很多時候我們都需要自己去定製一些東西。web開發的東西比較多, 我們先掌握一些必要知識點,剩下的就是CRUD開發。 快速的創建一個springboot ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...