1. 程式人生 > 實用技巧 >NX二次開發-UFUN建立角度尺寸標註UF_DRF_create_angular_dim

NX二次開發-UFUN建立角度尺寸標註UF_DRF_create_angular_dim

此作業的要求參見:https://edu.cnblogs.com/campus/nenu/2020Fall/homework/11206

該作業採用的程式語言為Python,其程式碼的地址為:https://e.coding.net/xucancan1/count_words/count_words.git

我用的是git和tortoisgit將檔案傳入到coding.net上的

功能1小檔案輸入

功能2支援命令列輸入英文作品的檔名

功能3支援命令列輸入儲存有英文作品檔案的目錄名

功能4從控制檯讀入英文單篇作品

一. 功能1

重難點:

(1)對於第一個題,如何把檔名輸入到命令列引數上,讓命令列的引數來進行處理問題?注意這裡要與input()函式的輸入區分開來

如果我們使用input()函式獲得輸入資料而進行處理,這種在命令列上執行時,會要求敲兩次回車鍵才能執行,第一行輸入的資料都輸入到了sys.argv中,而第二行輸入的資料,才是被輸入到了input()了,然後通過input()來處理,雖然結果相同,但顯然不符合題意。

正確做法:引入sys包,通過sys,argv陣列來接收輸入的檔名以及其他引數 (ps:不是用input來接受檔名進行處理)

(2)如何通過命令列輸入的檔名來讀取對應的檔案?

通過使用sys.argv[0],sys.argv[1],sys.argv[2],來進行操作,一般sys.argv[0]指的是pthon檔名的路徑,sys.argv[1],sys.argv[2],才是接下來的要處理的引數

對於開啟檔案用open()函式:f=open("sys.argv[0]",''r",encoding="UTF-8"),這裡有一個很容易錯的問題,那就是這個需要加一個utf-8,當時在這個問題卡了很久,不明白問題所在,通過百度才明白。

由於.py檔案預設ASCII編碼,中文在顯示時會做一個ASCII到系統預設編碼的轉換,這時會報錯,所以在open()函式里加‘encoding='utf-8’,意為以位元組為單位對Unicode進行編碼儲存,這樣遇到中文也不會出錯。

(3)如何將檔案的內容分割成單詞,然後儲存到列表中?

我用的是split()函式按照一定的規則進行分割;首先將檔案統一轉換成小寫(大寫也行)進行預處理,避免重複計算,

然後用list()函式將每個單詞列表化和filter()函式消除列表中的空格

(4)如何統計總單詞數和統計各個單詞出現的次數?

對於這個問題,我本來想著用一個for迴圈來遍歷列表。將每個單詞出現的個數用字典來統計的,但是後來想了一下這個有點浪費體力,然後剛好有一個collection包裡有一個counter()函式,直接統計列表中的單詞,返回的結果是一個元組的列表,剛好符合我要的功能。接著就是遍歷這個字典統計各個單詞的出現的個數以及進行列印。

(5)如何統計單詞數出現最多的前n個單詞的列表?

這裡其實可以使用sort函式對字典的鍵值進行排序,然後選擇只打印前10個單詞以及出現的個數,但是這樣多了一個for迴圈判斷,我果斷放棄了,又選擇一個一個內建函式most_common(10),這個函式好處作用是統計了前10的單詞,返回是一個字典,然後只需列印遍歷這個字典就行。

重要程式碼:

#功能1:小檔案輸入。
def count_words(filename):
    #print("c")
    s=".txt"
    if s in filename:
        path=filename
    else:    
        path=filename+s

    try:
        with open(path,"r",encoding="UTF-8") as f_obj:
             content = f_obj.read().lower()
    except FileNotFoundError:
        msg = "sorry,the file " + filename + " does not exist."
        print(msg)
    else:
    
        #為避免重複計算大小寫單詞,所以將所有單詞全部轉換為小寫
        lists= re.split(r'[",", ".", "!", "?", ";", ""","--","\n"]', content)     #通過正則表示式和split()函式生成檔案內容的列表 
        lists= list(filter(None, lists))     #消除列表中的空格
        words=Counter(lists)
        #遍歷字典,統計鍵值對數
        num=0
        for key,value in words.items():
            num+=1
        #功能1不輸出words,功能2輸出words
        if sys.argv[1]=="-s":
            print("total"+" "+str(num))
        else:
           print("total"+" "+str(num)+" words")
        #most_common(n)返回統計單詞數出現最多的前n個單詞列表
        maxwords=words.most_common(10)
        for i in maxwords:
           print("%-10s%5d"%(i[0],i[1]))

執行效果截圖:

二. 功能2

重難點:

(1)如何支援直接輸入檔名,而不需要加字尾名.txt和-s就可以統計檔案的各個單詞次數呢?

對於這個問題,要與第一題區分,第一題是加-s就執行執行這個檔案,我們只要判斷一下sys,argv[1]是否是-s,如果有,就執行第一個功能,如果沒有就執行第二個功能,接著然後在輸入的檔案後面新增一個.txt字尾。

(2)如何處理這個檔案的大小寫單詞和非字母對單詞詞統計的影響?

對於這兩個問題,當統計次數時,首先解決大小寫的影響,我用的是.lower()函式將全部單詞轉化為小寫,(這裡也可以用.upper()函式轉換成大寫),這樣做可以避免重複計算單詞。其次是解決非字母的字元,我使用的是findall(r"[a-z0-9^-]+",f.read().lower())函式來處理的,它的作用是通過正則表示式和findall()函式排除不符合的字元,從而生成檔案內容的列表,其實我後來想了一下,其實也可以用replace()函式把那些不符合單詞的字元替換掉。

(3)有關功能1和功能2的區別?

功能1和功能2除了上述的輸入有區別外,還有輸出的區別:功能2是要輸出“words”這個單詞的,功能1不輸出該單詞。

重要程式碼:

#功能2:支援命令列輸入英文作品的檔名
def count_words02(name):
    
    # 判斷傳入的命令列引數字尾部分是否含有.txt
    d=".txt"
    if d in name:
        path=name
    else:     #若沒有,要加上,再作為開啟路徑
        path=name+d
   
    f=open(path,"r",encoding="utf-8")     
    lists=findall(r"[a-z0-9^-]+",f.read().lower())#通過正則表示式和findall()函式生成檔案內容的列表
    words=Counter(lists)
    #遍歷字典,統計鍵值對數
    num=0
    for key,value in words.items():
        num+=1
    #功能1不輸出words,功能2輸出words
    if sys.argv[1]=="-s":
        print("total"+" "+str(num))
    else:
        print("total"+" "+str(num)+" words")
    #most_common(n)返回計數值最大的n個元素的元素列表
    maxwords=words.most_common(10)
    for i in maxwords:
        print("%-10s%5d"%(i[0],i[1]))

執行效果截圖:

三.功能3

重難點:

(1)如何判斷你輸入的引數是檔案還是資料夾?

對於這個問題,我百度了一下,首先需要os這個包,這個包裡面帶了一個os.path.isdir()函式,它的作用是用於判斷某一物件(需提供絕對路徑)是否為目錄,這個要與os.path.isfile()函式區分開來他的作用是判斷物件是否為一個檔案,具體用法區別詳見https://blog.csdn.net/m0_37443131/article/details/81231763

(2)如何獲取當前.txt檔案的絕對路徑?

這個問題困擾了很久,我當時想取指定檔案或目錄的絕對路徑(完整路徑),想起OS模組不是有個取檔案絕對路徑的方法os.path.abspath(),結果出現了很大的問題。

例如:獲取檔案‘test.py’的完整路徑

test.py的完整路徑是:D:\python_t\IO目錄處理\test.py,而不是D:\python_t\test.py,看到這個結果我就淚奔了,不是取絕對路徑麼?怎麼不是真實的完整路徑?上級目錄不見了?很多疑惑?

其實通過這個例子,我們可以看出os.path.abspath()函式無法獲取指定檔案的絕對路徑,而是需要加檔案路徑os.path.abspath(path),所以我為了獲得絕對路徑,分為了兩個部分,第一部分是獲得該資料夾的上級目錄domain = os.path.abspath("."), domain獲取的是當前檔案的上一級目錄資料夾,然後加上當前資料夾;第二部分是獲得需要訪問的.txt檔案,兩個部分加起來,就是.txt檔案的絕對路徑。

詳細用法https://blog.csdn.net/funnypython/article/details/78733115

(3)在獲得資料夾路徑時,需要把所有的\\更改為/

因為python返回路徑時目錄級別都是\\這個形態的,需要將他轉換成 / 這個形態,用了replace()函式替換

(4)如何統計資料夾下的.txt檔案的單詞出現次數?

由於獲得了該資料夾的絕對路徑,再加上需要訪問的.txt檔案,兩部分加起來就是該.txt檔案的絕對路徑,然後用open()函式,對這個檔案進行讀取,去除一些不符合單詞的字元,然後用counter()函式統計單詞出現的個數。

重要程式碼:

 #功能3
    elif os.path.isdir(sys.argv[1]):
       #print(sys.argv[1])
        filecount(sys.argv[1])
#功能3:傳入資料夾,批量統計資料夾下各檔案的單詞的個數
def filecount(filename):
    files=os.listdir(filename)#將資料夾下的檔案列表化
   # print(files)   #輸出該檔案下所有的檔案
    print("\n")
    domain = os.path.abspath(".") #獲取檔案的上一級目錄資料夾,輸出的是D:/homework01/
    domain = domain.replace('\\', '/') + '/' + filename + '/'   #將所有的\\變成“/”,且加上當前檔案,返回相當於D:/homework01/book/
    
    for file in files:  #遍歷檔案下的所有檔案
        
        path=domain+file   #這才是該檔案的真實路徑,path=D:/homework01/book/file.txt
        
        (filename1, extension) = os.path.splitext(file)#將檔名與字尾分開,將檔名單列出來
        print(filename1)   
        f=open(path,"r",encoding="utf-8")     
        lists=findall(r"[a-z0-9^-]+",f.read().lower())#通過正則表示式和findall()函式生成檔案內容的列表
        words=Counter(lists)  #Counter函式是用來跟蹤值出現的次數,以字典的鍵值對形式儲存,其中元素為key,其計數為value  
        #遍歷字典,統計鍵值對數
        num=0
        for key,value in words.items():
           num+=1
        print("total"+" "+str(num)+" words")
           
        #most_common(n)返回計數值最大的n個元素的元素列表
        maxwords=words.most_common(10)
        for i in maxwords:
           print("%-10s%5d"%(i[0],i[1]))
        print('------------------')
        

執行效果截圖:

四.功能4

重點難點:

(1)如何對功能4的理解?

其實開始看這個功能4時,我還蒙,但是看了一下測試用例,我慢慢明白了,首先確定the_show_of_the_ring是一個檔案,其次哪個>wf -s < the_show_of_the_ring,這個<符號是一個重定向符,-s是新增的區別於其他功能的標誌,所以題意是統計重定向的檔案的單詞個數。

(2)如何在cmd命令臺接收一大段英文文章?

首先確定sys.argv陣列是不能接受這麼大段英文文章的,所以我引用了input()函式,sys.argv用來儲存這個.py檔案路徑,我先判斷一下輸入,sys.argv陣列的裡面內容的個數為1,就表明它接下來要輸入一段英文文章;接著我用input()函式來接收這段英文。然後通過input()函式接收的英文進行分割處理成單詞列表,接下來就是統計單詞個數了

重要程式碼:

#功能4:輸入一篇文章統計單詞字數
    if(len(argv)==1):
        str = input()
        str = re.sub('[^a-zA-Z]',' ',str)  #sub()函式將不為字母的替換空格
        count_words03(str)

(3)如何統計重定向檔案的單詞,即< the_show_of_the_ring?

對於這個問題,我完全沒有頭緒,後來通過偉大的百度,查閱了一下windows下檔案重定向的相關問題,大概總算明白了是什麼回事。然後看到了一個sys.stdin.readline() 函式,這個函式功能是儲存重定向的檔名接著去讀這個檔案的內容,返回這個檔案的內容。剛好返回的內容是我們需要的,我們可以通過相關處理變成單詞列表,繼續統計該列表的單詞。

sys.stdin.readline()函式用法詳見:https://www.jb51.net/article/169914.htm

(4)如何判別wf.py -s是執行功能4的重定向呢?

這個功能區別於功能1,功能1中的sys.argv數組裡面的len(sys.argv)是3,而功能4中的len(sys.argv)數組裡面的是2,接下來用sys.stdin.readline() 函式接收重定向的檔案,並返回該檔案的內容。

重要程式碼:

#功能1和功能4
    elif sys.argv[1]=='-s':
        if(len(argv) == 3):   #執行功能1
            #print(sys.argv[2])
            count_words(sys.argv[2])
               
        elif(len(argv)==2):   #執行功能4:重新定向檔案
           redirect_words = sys.stdin.readline()  # 儲存重定向的檔名接著去讀這個檔案的內容,返回這個檔案

重要程式碼:

#功能4:重定向
def count_words03(string):
    print("\n")
    lists = string.replace('\n', ' ').lower().split()  # 用空格去掉所有的\n,且轉換成小寫,進行分割單詞
    words=Counter(lists)  #Counter函式是用來跟蹤值出現的次數,以字典的鍵值對形式儲存,其中元素為key,其計數為value  
    #遍歷字典,統計鍵值對數
    num=0
    for key,value in words.items():
        num+=1
    print("total"+" "+str(num)+" words")
           
    #most_common(n)返回計數值最大的n個元素的元素列表
    maxwords=words.most_common(10)
    for i in maxwords:
        print("%-10s%5d"%(i[0],i[1]))
     
        

#定義main函式
def main(argv):
    #功能4:輸入一篇文章統計單詞字數
    if(len(argv)==1):
        str = input()
        str = re.sub('[^a-zA-Z]',' ',str)  #sub()函式將不為字母的替換空格
        count_words03(str)
        
    #功能1和功能4
    elif sys.argv[1]=='-s':
        if(len(argv) == 3):   #執行功能1
            #print(sys.argv[2])
            count_words(sys.argv[2])
               
        elif(len(argv)==2):   #執行功能4:重新定向檔案
           redirect_words = sys.stdin.readline()  # 儲存重定向的檔名接著去讀這個檔案的內容,返回這個檔案的內容
           
           redirect_words= re.sub('[^a-zA-Z]',' ',redirect_words)
           count_words03(redirect_words)
                 

執行效果圖:

五 功能5

在檔案中統計給定的單詞長度為m的次數前n個的單詞

重難點:

(1)如何解析題目的需求?

我為了把這個功能模組整合到原先設計好的程式框架中,特定對功能5做了標記,這是為了與其他功能的執行區分,用了-h這個標記來執行功能5,剩下的就是功能5的需求進行設計。

(2)如何將兩個變數引數輸入進去,並且讓它們執行相應的功能?

對於這個問題我是用input()函式來接收它們,由於input()函式返回的是字串型別,所以我用了int()函式將他們強制轉換成整形,然後把它們輸入到功能5模組中進行處理,接著就是讀取檔案,將檔案內容按照正則表示式分割成單詞列表。

#功能5: 在檔案中統計給定的單詞長度為m的次數前n個的單詞
    if(sys.argv[1]=="-h"):
        str1=input()
        a=int((str1.strip()))
        str2=input()
        b=int((str2.strip())))
        count_words04(sys.argv[2],a,b)
        

(3)注意input()函式,這個函式它也接收空格,回車換行等字元,在將它強制轉換時,需要用striip()將這些過濾掉,然後才能用int()函式轉成整數

(4)如何獲得檔案中單詞長度為m的單詞次數前n的單詞列表呢?

首先,解決這個問題分為兩步,第一步在檔案中獲取所有單詞長度為m的單詞;我先用counter()函式統計各個單詞的出現的次數,由於counter()函式返回的是單詞元組的列表,在這個問題,我開始以為counter()函式返回的是字典,後面造成了一定隱形錯誤,然後我遍歷這個列表,找出所有單詞長度為m的單詞,接著將它們逐個新增到一個空字典中;第二步在第一步的基礎上,統計單詞次數前n的單詞;由於獲得了所有單詞長度為m的單詞的字典,接著對這些字典的鍵值進行排序,我本來是想用一個氣泡排序進行排序的,後來想著這樣太麻煩了,所以直接用most_common()函式統計出前n的單詞 以及次數。

 words=Counter(lists)
        #遍歷元組,統計鍵值對數
        num=0
        words_dic = {}
        for key,value in words.items():
            d={}
            if(len(key)==lent): #統計長度為lent的單詞
                d[key]=value
                words_dic.update(d)
                
            num+=1
        print("\n")
        print("total"+" "+str(num)+" words")
        print("你選擇了長度為"+str(lent)+"的單詞")
        print("統計單詞數出現最多的前"+str(n)+"個單詞的列表")
        words_list=Counter(words_dic)

(5)關於most_common()函式的錯誤用法的血淚史。

錯誤1:呼叫most_common()函式有限制,我一直以為可以通過字典來呼叫它,然後我一直執行,不停的報錯,(ps:我英語差,當時看不懂錯誤提示)然後我將錯誤提示提交給百度,搜查相關的問題,然後知道了問題關鍵所在,原來是most_commom()函式的用法出現問題,接著我查了一下most_commom()函式的用法,字典不能呼叫它,列表可以呼叫它。然後我就再次使用counter()函式,將字典轉成帶有元組的列表,這樣就可以使用most_commom()函數了。

錯誤2:most_common()函式只返回前n個單詞,它不管第n+1個單詞是否與第n個單詞相等,這樣造成的後果會丟掉那些原本第n+1個單詞和第n個單詞相等的單詞。

錯誤執行結果截圖:

從上圖可以看出,長度為4的單詞排序,取單詞數出現前3的單詞,第4,第5,第6的單詞個數與第3的單詞個數相等,但是它們被捨棄了,沒有被顯示,這種返回結果非常不好。

針對上面的出現的問題,我重新定義了一個get_count(dct, n)函式來解決,當相等的情況下,相等的需要全部被顯示出來。

#返回統計單詞數出現最多的前n個單詞列表
def get_count(dct, n):
  data = dct.most_common()
  val = data[n-1][1] 
  return list(takewhile(lambda x: x[1] >= val, data))

正確執行結果截圖:

重要程式碼:

def main(argv):
    #功能5: 在檔案中統計給定的單詞長度為m的次數前n個的單詞
    if(sys.argv[1]=="-h"):
        str1=input()
        a=int((str1.strip()))
        str2=input()
        b=int((str2.strip()))
        count_words04(sys.argv[2],a,b)
        
#功能5:查詢特定長度單詞的個數
def count_words04(filename,lent,n):
    s=".txt"
    if s in filename:
        path=filename
    else:    
        path=filename+s

    try:
        with open(path,"r",encoding="UTF-8") as f_obj:
             content = f_obj.read().lower()
    except FileNotFoundError:
        msg = "sorry,the file " + filename + " does not exist."
        print(msg)
    else:
    
        #為避免重複計算大小寫單詞,所以將所有單詞全部轉換為小寫
        lists= re.split(r'[",", ".", "!", "?", ";", ""","--","\n"]', content)     #通過正則表示式和split()函式生成檔案內容的列表 
        lists= list(filter(None, lists))     #消除列表中的空格
        words=Counter(lists)
        #遍歷元組,統計鍵值對數
        num=0
        words_dic = {}
        for key,value in words.items():
            d={}
            if(len(key)==lent): #統計長度為lent的單詞
                d[key]=value
                words_dic.update(d)
                
            num+=1
      
        print("total"+" "+str(num)+" words")
        print("你選擇了長度為"+str(lent)+"的單詞")
        print("統計單詞數出現最多的前"+str(n)+"個單詞的列表")
        print(words_dic)
        words_list=Counter(words_dic)
        # 本來想用most_common(n)返回統計單詞數出現最多的前n個單詞列表,後來當有多個單詞相等的時候,這個函式只取前n個,其實第n+1個也是跟第n值相等,但是這個函式不能實現
        maxwords=get_count(words_list,n)
        #maxwords=words_list.most_common(n)
        print("\n")
        print("統計結果為:")
        for i in maxwords:
           print("%-10s%5d"%(i[0],i[1]))
    

執行結果截圖:

6.psp

功能 預計花費時間 實際花費時間 時間差 原因
功能1 80min 123min 43min 對python命令臺輸入輸出不太熟悉
功能2 60min 105min 45min 對引數輸入沒把握好,且處理字尾名花了一段時間
功能3 90min 146min 76min 對於獲取絕對路徑不理解,花了很久解決這個問題
功能4 100min 152min 52min 首先對題目的解析花了一段時間,且設計相關功能也花了很多時間
功能5 40min 60min 20min 功能測試,以及功能設計需求超出了時間
測試 20min 123min 103min 對於python檔案需要轉換成.exe檔案,安裝pyinstaller嚴重超出了時間

7.總結

完成這個部分作業,我大概分為了三個階段:

第一階段熟悉安裝使用git和totorisgit,熟練將檔案從coding.net或github中pull下來或者push到雲端。

第二階段1-5功能實現的程式碼設計

第三階段將.py檔案轉換成.exe檔案

對於第一階段,說句實話,花了很久時間才把totorisegit這個工具學會(當然也可以用git命令列),用它可以直接push&pull程式碼,而且可以將程式碼push到雲端儲存著,真的很方便,雖然在學習使用工具這個過程中摸索地很痛苦,但是學會了後,我感覺totorisgit工具和雲端倉庫真的太nice了!

對於第二個階段功能程式碼設計,python很多方法的實現完全可以呼叫相關函式來執行,我在這個問題上由於python知識儲備不是很足,所以花了很多時間研究其中的函式,最終才將相關的函式運用到實際操作中。個人建議:如若遇到不懂的盲點或者疑惑,可以自己先獨立去百度,知乎等搜尋,這樣可以全面徹底掌握自己的盲區和疑惑。

對於第三階段下載安裝pyinstaller,將.py檔案轉換成.exe檔案,真的我也摸索了很久。主要是在.exe檔案的查詢上,一開始不知道它轉化到哪裡了,後來查詢百度,發現它存到了dist檔案中

通過這次的程式設計實踐,讓我學習到了很多以前沒有學到的知識,同時也讓我知道了自己的不足,我還需要不停地努力!

關於totoisgit和git安裝是相關問題:

1.Git將原生代碼推到遠端倉庫的步驟:[https://blog.csdn.net/weixin_39910711/article/details/89955544]

2.利用totorisgit在github上下載程式碼:https://blog.csdn.net/zdp072/article/details/51966586

3.遠端倉庫連線錯誤時,如何清除連線[https://www.cnblogs.com/wollow/p/10840016.html]

4.認證失敗時,怎麼辦[https://www.jianshu.com/p/c095300d569e]

5.使用Git客戶端下載程式碼的流程[https://blog.csdn.net/wyqwilliam/article/details/82881609]

6.Git clone和Git pull的簡要區別[https://www.jianshu.com/p/c6a0397ec6f5]

7.如何將.py檔案轉化為可執行的.exe檔案:https://blog.csdn.net/qq_36604847/article/details/81509113