# PYTHON課程 > 打好基礎 > 給學生 [TQC認證](https://www.tqc.org.tw/TQCNet/CertificateDetail.aspx?CODE=DrK4Zfi2X3Q=) ## 網路資源 * 中學生解題系統 https://zerojudge.tw/ ## 課程進度 ### 第1節 * python 安裝環境:用Anaconda當作開發環境,優點是整合了Package安裝、Environment建設及寫程式的環境 * 到官網下載 https://www.anaconda.com 最新版Anaconda安裝 * jupyter:寫phthon程式 * 點選執行 * 出現cmd視窗及網頁,若未自動執行網頁,在cmd視窗中複製網址到瀏覽器貼上執行 * 網頁會出現本機所有檔案,可以在這裡管理檔案、新增phthon程式,執行python程式 * 線上記筆記: * [HackMD](https://hackmd.io/) * [完整功能介紹](https://hackmd.io/c/tutorials-tw/%2Fs%2Ffeatures-tw) * python 基礎數學計算 ``` Python + - * / ``` ### 第2節 * 註解 * 單行註解 # * 螢幕輸出結果:print() * python 變數 * 變數名稱的設定 * 名稱有大小寫之分 * 不可使用系統保留字或[內建函數](https://docs.python.org/zh-tw/3/library/functions.html)名稱,若使用了內建函數名稱當作變數,程式不會出錯,但是會讓原先的函數功能喪失 * 變數名稱內不可有, $ 以及不可由數字開頭 * 變數名稱可以用中文,但不建議 * 規則:_ ,駝峰式 * 變數名稱. 按tab鍵可以叫出快顯功能表(記得下參數)此方法Jupyter有用 ```python= #查詢內建函數名稱 dir(__builtins__) # 檢查系統保留字 import keyword keyword.kwlist ``` * 變數的性質:數字、字串、布林 * type() * 利用變數做計算(作業一) ``` Python #作業一 hour_salary = 125 #時薪 # 一天工作8小時,一年工作300天,請利用變數計算年薪 month_fee = 9000 #每月花費 # 請利用變數計算每年可以結餘的錢,並顯示 ```` ### 第3節 * python 數學四則運算 ``` python #除了 + - * / a ** c # a的c次方 x = 9 % 5 #9除以5的餘數指定給x x = 9 // 5 #將9除以5的整數部分指定給x,此範例x=1 ``` * 計算的優先順序(以下方順序由上到下) * () * 次方 * 乘法 * 除法 * 餘數% * 整數// * 加法 * 減法 * 指派運算子 ```python += a+=b a=a+b -= a-=b a=a-b *= a*=b a=a*b /= a/=b a=a/b %= a%=b a=a%b //= a//=b a=a/b 取整數的部分 **= a**=b a=a的b次方 ``` * for迴圈1 ``` python #結構:使用range for i in range(1,20): print(i) # range(從哪一個數開始, 等於這個數就結束迴圈) ``` ``` python #作業二:請設計從3開始,公比都等於2的等比數列,請從3開始顯示10個數 ``` [等比數列](https://zh.wikipedia.org/wiki/%E7%AD%89%E6%AF%94%E6%95%B0%E5%88%97) ### 第4節 * 上次作業解析 * 找規則(2種) * 依規則解決 * 需要指令 for i in range(0,10) a*= print * python 基本資料型態(配合變數) * 先宣告變數,但未指定型態 ``` python var = None # 代表尚未設定型態,此時用type(var),會顯示NoneType ``` * 布林:True False ``` python #看看範例: x = 1 z = x == 1 #顯示z會出現??? ``` * 數字 * 整數與[浮點數](https://docs.python.org/zh-tw/3/tutorial/floatingpoint.html)會自動判斷 * 浮點數:因為電腦是2進位為基礎,因此只要是小數,就只能產生近似值,再用近似值來顯示我們看得懂的樣式 ```python round() #進位,如果最左邊的數是奇數則使用四捨五入,如果是偶數則使用五捨六入,如round(1.5)=2 round(2.5)=2 round(5.364, 1) #四捨五入進位到小數第1位,後面的1可以省略,視同變成整數 ``` * if判斷式1 ``` python if ( a < 100) : print(a) # 條件式的()可以省略 ``` ``` python #作業三:請設計變數a為小數,先進行四捨五入,再判斷如果變數a大於100,則變數a強制變成100並輸出到螢幕 ``` ### 第5節 * 上週作業解析 * 數字的2進位 * 0b開頭的表示2進位 ``` python bin() #轉換成2進位 #範例 x=20 y=bin(x) print(y) ``` * 0o開頭的表示8進位 ``` python oct() #轉換成8進位 #使用方式參考bin()的範例 ``` * 0x開頭的表示16進位 ``` python hex() #轉換成16進位 #使用方式參考bin()的範例 ``` ``` python input() #輸入資料,但是資料為str,要計算須轉數字型態 int() #將資料型態強制轉換成整數,範例int(x) float() #將資料型態強制轉換成浮點數 eval() #自動判定資料為int或float型態 abs() #計算絕對值 pow(x,y) #返回x的y次方 ``` * 進位計算機:https://calc.iskane.me/ * if判斷式2 ``` python if (條件) : 程式 elif (條件 and 條件) : 程式 elif (條件 or 條件) : 程式 else: 程式 # 條件式的()可以省略 ``` ``` python #作業四:請列出100-200之間的偶數 ``` ### 第6節 * 上週作業解析 * 字串 https://docs.python.org/3.4/library/string.html ``` python #變數中字串設定方式 y = "hello" y = 'hello' z = '''hello word''' z = """hello word""" #用三個引號包起來的方式可以換行,會加入\n這個字元 #取出字元 z[0] #拿出第1個字母,把字串當串列用,但不能更改內容元素 z[-1] #拿出最後1個字母 #-號代表從後面數過來 #字串連接 y + z #+將多個字串連起來 #另外可以用print("abc", "def", type(var))這種方式,每一個參數中會有一個空格 ``` * 流程規劃 * 使用[drawio](https://app.diagrams.net/) * 注意圖形的使用意義 * ![](https://i.imgur.com/5oaYg6Q.jpg) * ![](https://i.imgur.com/SnaRtVh.jpg) * 範例 * ![](https://i.imgur.com/u7asoz5.png) ``` python #作業五:請設計流程圖:變數a內容為可輸入字串,先計算a的字數,再判斷如果字數大於10個字,則顯示"太長了",如果字數介於5-9個字,則顯示"剛好",若字數小於5個字則顯示"太短了" ``` ### 第7節 * 上週作業解析 * 逸出字元(在jupyter中,要使用print才有用,而且下列不是全部都有反應) * \\ = 反斜線 * \' = 單引號 * \" = 雙引號 * \a = 鈴聲 * \b = 倒退 * \f = 換頁 * \n = 換列 * \r = 游標移至最左邊 * \t = 水平跳格(TAB鍵效果) * \v = 垂直定位 * \x = 16進位表示 * \N{id} = Unicode資料庫ID * \uhhhh = Unicode 16位元之十六進位值 * \Uhhhh = Unicode 32位元之十六進位值 * \xhh = 十六進位值 * \o = 八進位表示 * \0 = null (是null字元,python不像C用null字元來判斷字串結束) * 字串前加上r可以取消字串中的逸出字元 ``` x = r'王小\n明' ``` * 字串與整數相乘代表重複該字串的整數次數 ```python= #字串函式 len() #顯示字串的字數 str() #強制轉換為字串 chr() #傳回數字參數的代表字元,用ASCII值,如chr(97)顯示a ord() #傳回字元參數的Unicode值,參數只能放1個字元 方法:變數.方法 .lower() #轉換成小寫字 .upper() #轉成大寫字 .title() #轉成第一個字母大寫,其他是小寫 .rstrip() #刪除字串尾端多餘的空白 .lstrip() #刪除字串開始多餘的空白 .strip() #刪除字串頭尾兩端多餘的空白 字串前綴 word = u'字串內容' #表示後面字串以 Unicode 格式 進行編碼,一般用在中文字串前面 word = r'字串內容' #去掉反斜槓的轉移機制 word = b'字串內容' #表示後面字串是bytes型別(物件) #網路程式設計中,伺服器和瀏覽器只認bytes型別資料 word = f'字串內容' #python3.6之後可用 #表示在字串內支援大括號內的python表示式 #例如 #name = ‘processing’ #print(f’{name} done in {time.time() - t:.2f} s’) ``` * [ASCII是什麼](https://zh.wikipedia.org/wiki/ASCII) ``` python #作業六:請依據別人設計的流程圖,將他轉變為程式,當無法完成時,請找出它的問題 ``` ### 第8節 * 上週作業解析 * 注意符號:() [] {} * 關於資料儲存:資料本體與索引 * 資料處理1:list 序列 * 認識list資料儲存結構 * 索引-資料 * 元素可以同時儲放不同型態的資料,或者另一個list,或是字典 * 索引值未指定時使用數字,開頭為0 * 索引值-1代表最後一個元素,-2代表最後第2個元素 * 將兩個列表用+等於將兩個列表合併為一個列表,後面列表的元素就會接在前面列表元素的後面 ```python #賦值 li = [] #宣告一個空的列表 li = [1, 2, 3, 'stn'] liz = [1,2,3, [10,20,'str']] #取用 li[0] #拿出第1個值 li[3][2] #取出多元串列(串列內的元素也是串列)的值 li[start:end:step] #讀取從索引start到(end-1)索引的元素,區間為step(可省略) li[:3] #從頭取3個值 li[2:] #從第3個值(因為開頭是0)取到最後 li[-3:] #拿出後面三個值 li[:] #取得所有元素 li[2:10:2] #從第三個開始取四個,區間為2 v1,v2,v3,v4=li #將li的四個元素依序指定給v1 v2 v3 v4,這樣寫法較有效率 ``` * 巢狀迴圈:兩個for的應用 ```python for i in list(A): # A群組同學的錢[12, 27, 25, 88, 63] # B群組同學的錢[55, 88, 32, 50, 67] # 作業8: # 兩個群組中哪兩位同學的錢加起來是10的倍數 ``` ``` python for i in range(1,10): #作業7:請設計一個九九乘法表 ``` ### 第9節 * 上週作業解析 * 資料處理2:list的拷貝與增刪修 ```python li = li * 3 #將串列元素重複三次 li1 = li2 + li3 #將li2和li3串列合成一個li1的串列,也可以用 li2+=li3 #拷貝 li1 = li2 #將li1串列的位址拷貝給li2,所以更動li2時也會影響li1\ li1 = li2[:] #如果要拷貝內容而非位址用此方法,這樣兩個串列之間不會互相影響 #新增 li.append(111) #把111接在li的最後一個元素 #參數也可以放另一個串列 li.insert(索引, 元素內容) #插入新的元素,在該索引的位置,原有元素會向後排 li1.extend(li2) #將li2的元素都併入li1中,變成一個串列 #修改 li[18] = 4 #修改該元素的值 #刪除 del li[3] #刪除li索引值3的元素 del li[2:4] #也可以和[:]或[::step]的方法結合 del li #刪除整個列表 #使用del刪除不會有回傳值,如果要回傳值,需使用pop() vname = li.pop(2) #參數是索引值,如果空白代表刪除最後一個元素 li.remove("car") #刪除元素內容為car的元素 ``` * for與list的應用 ```python #作業8 for i in list(A): # 班上同學的每周零用錢(依照號碼): 10, 20, 20, 100, 70, 50, 60, 140, 200, 0 ,50 # 請設計一個輸入框,然後可以一筆一筆的將錢的數量輸入,並存放到list中 #再計算並輸出偶數同學的零用錢總和是多少錢 ``` ### 第10節 * 上週作業解析 * 資料處理3:list的進階應用 ```python max(li) #列表中的最大值,但有非數字元素會出錯 min(li) #列表中的最小值,但有非數字元素會出錯 sum(li) #列表中所有元素的總和,但有非數字元素會出錯 len(li) #列表中有多少元素 li.reverse() #反轉串列,不會有任何回傳值,要列出結果需要再呼叫li li[::-1] #將串列顛倒排序 li.sort() #將串列由小到大排序,如果要從大到小,參數加上reverse=True #排列英文時,建議先全改成大寫或小寫比較不會有錯 #元素內有非數字時會出錯 #不會有任何回傳值,要列出結果需要再呼叫li new_list = sorted(li) #將li串列由小到大排序,並將結果指給new_list串列,原串列不動 #如果要從大到小,加上參數 sorted(li, reverse=True) #,不會有任何回傳值,要列出結果需要再呼叫li li.index("abc") #abc在串列中第一次出現的索引值 li.count("abc") #abc在串列中出現的次數 char.join(li) #將li串列全部串再一起,char是串接的字元 #但是要注意格式,char是字串,但串列內的數字和文字無法直接合併,只要有數字都不行 ``` * break 強制離開for迴圈 * 搭配if,符合特定條件就跳離迴圈 ```python # 作業9:請找到list裡面3的倍數,並告訴我們是哪一個數字及索引值 #print格式化 #print("第{}個數字是3的倍數:".format(sid), iscore) #print("第%d個數字是3的倍數:"%sid, iscore) #注意索引編號從0開始,但是人習慣的是從1開始 ``` ### 第11節 * 上週作業解析 * print格式化 * python3的方法 ```python= print("{}資料內容{}資料內容{}以下類推".format(var1,var2,var1*var2)) #搭配format的用法 print("{0}資料內容{1}資料內容{2}以下類推".format(var1,var2,var1*var2)) #{}內的數字為索引值,format的第一個值得索引值為0,其他類推 print('{0} is {1}!!'.format(666, 'caterpillar')) prinit('{real} is {nick}!!'.format(real = 666, nick = 'caterpillar')) #編號要依照數量,順序可以調換 #其他格式設定值 {:10d} 預留10個寬度來列印,預設數字靠右 {:>10d} 預留10個寬度來列印,強制靠右列印 {:<10d} 預留10個寬度來列印,強制靠左列印 {:^10d} 預留10個寬度來列印,強制置中列印 {:3f} 保留3位小數,做四捨五入 {:+.3f} 保留3位小數,做四捨五入,並帶符號(+號,可以改) {:.0f} 不帶小數,做四捨五入(數字可改變) {:10.3f} 預留10個寬度來列印,並保留3位小數,做四捨五入 {:0>5d} 預留5個寬度來列印,數字靠右,空白補0 {:x<5d} 預留5個寬度來列印,數字靠左,空白處補x {:,} 列印千分位的逗號 {:.3%} 列印百分比,預留3位小數 {:.3e} 列印科學記號,預留3位小數 :s 以 str 的形式輸出文字 :f 以浮點數形式輸出數字 :d 以十進位形式輸出數字 :b 以二進位形式輸出數字 :o 以八進位形式輸出數字 :x, :X 以十六進位形式輸出數字 :e, :E 以科學記號形式輸出數字 :% 以百分比形式輸出數字 :c 以字元形式輸出(ASCII) print("write to docs this word", file=fileObj) #將文字列印到檔案 #預設file=sys.stdout,輸出到螢幕 ``` * python2的方法 ```python= print('整數%d,小數%.2f,字串:%s' % (1, 99.3, 'Justin')) #輸出 整數1,小數99.30,字串:Justin %% 在字串 中顯示% %d 有符號整型⼗進制 %i 有符號整型⼗進制 %o 有符號⼋進製值 %u 過時類型 – 等同 %d %x 有符號⼗六進制(⼩寫),將整數以16進位方式輸出 %X 有符號⼗六進制(⼤寫),將整數以16進位方式輸出 %e 浮點數指數格式 (⼩寫),將浮點數以10進位方式輸出,並使用科學記號 %E 浮點數指數格式 (⼤寫),將浮點數以10進位方式輸出,並使用科學記號 %f 浮點數⼗進制格式 %F 浮點數⼗進制格式 %g 浮點數格式。使⽤⼩寫指數格式,若指數⼩於 -4 或不低於精度的話;否則,會使⽤⼗進制格式 %G 浮點數格式。使⽤⼤寫指數格式,若指數⼩於 -4 或不低於精度的話;否則,會使⽤⼗進制格式 %c 單字符 (接受整數或單字符字符串),以字元方式輸出 %r 字符串 (以 repr() 內置函數轉換任何 Python 對象,使用repr()輸出字串) %s 字符串 (以 str() 內置函數轉換任何 Python 對象,使用str()將字串輸出) %a 字符串 (以 ascii() 內置函數轉換任何 Python 對象使用ascii()輸出字串) ``` * 資料處理4:tuple 元組 * 與list串列相同,但是不可以更動元素值與元素個數 * 若要更新元素內容,需重新定義整個tuple * 優點是資料更安全,也佔用較少的系統資源,增加執行速度 ```python= #設定tuple name_tuple = (元素1, 元素2, 元素3, ....) #如果元素只有1個,要加上,,如果沒有,,type就會變成int或str,而非tuple name_tuple = (元素1,) #讀取元素(索引值從0開始) name_tuple[2] #讀取所有元素用 for i in name_tuple: print(i) #支援切片,方式跟list一樣 name_tuple[1:2] #應用在list上面的方法如果不會更改元組內容都可以使用 s = list(name_tuple) #將元組資料轉換成串列,需指定到新變數上 max(name_tuple) #獲得元組內容最大值,元素內容需要都是數字 min(name_tuple) #獲得元組內容最小值,元素內容需要都是數字 #enumerate物件使用在元組 tuple(li) #將list資料轉換成tuple,需指定到新變數上 t = tuple(enumerate_name) ``` * continue、pass for迴圈的執行條件 * 搭配if,符合特定條件就不執行特定條件 ```python # 作業10:找出本次籃球賽分數大於30分的場次數量 # score=[33, 20, 40, 25, 49, 39, 27, 40] ``` ### 第12節 * 上週作業解析 * 資料處理5:enumerate * 將list tuple set等數值形式改用計數值與元素的方式傳回,傳回的數據稱為enumerate物件 * 多用於在for循環中得到計數,利用它可以同時獲得索引和值,即需要index和value值的時候可以使用enumerate ``` python #語法 obj = enumerate(iterable [,start = 0]),省略start設定,預設值是0 li1 = ["bask", "ask"] li2 = enumerate(li1) li2 = enumerate(li1, start = 10) #將初始值設為10 for i,z in li2: print(i,z) ``` * while迴圈 * 一定要設定離開迴圈的條件,不然會變成無窮迴圈 * 如果陷入無窮迴圈,按Ctrl+C,或是jupyter的停止按鈕 ```python= while 條件: 程式 # 只要條件成立就會執行程式,條件不成立就會跳出 #如果要製造無窮迴圈:\ while true: 程式 ``` ```python= #作業11: #設計一個可以重複輸入文字,並將輸入內容累計顯示,一直到按q就結束程式 ``` ### 第13節 * 上週作業解析 * * 資料處理6:字典 dictionary * 也是串列型的資料,但是利用 鍵-值 的方式配對儲存 * 取用時也是用鍵key取值value * 個別字典可以放進串列內,串列也可以放進字典內,字典內也可以放字典 * dictionary、LIST、enumerate的差異 ``` python score = {} #建立空字典 # v = {key:value, key:valu,....} score={'小民':90, '大徐': 80} #或是 score={ '小民': 90, '大徐': 80, } score['Keven'] = 95 #新增一筆字典到變數裏 print(score['大徐']) #印出大徐的數字 len(score) #字典內元素的數量 score.keys() #資料所有的key,回傳一個obj物件 score.values() #資料所有的value,回傳一個obj物件 ------------------------------------- #範例應用 for i in score.keys(): for i in score : if keyname in score: #檢查keyname(key值)是否在字典裡 for i,j in score.items(): #將字典內的鍵-值列一遍 #如果用for i,j in score: ,會將鍵拆成字,列出每個鍵的前兩個字 ------------------------------------- ``` ```python= #作業12: #利用字典的方式,將我們班上的人全部鍵入一個字典內,鍵值是姓名,內容是座號,然後利用for將資料印出,格式為座號=姓名 ``` ### 第14節 * 上週作業解析 * 資料處理7:字典 dictionary ```python del score[鍵] #刪除某個特定鍵元素 del score #刪除整個字典 score.clear() #刪除字典內所有元素,但字典還在,是個空串列 n_score = score.copy() #將字典完整複製到n_score內(id(記憶體位址)不同) n_score = score #n_score字典的內容指定為score內容(id(記憶體位址)相同) sorted(score.key()) #字典排序,依據鍵,參數也可以用.vlaues()及.items() score.fromkeys(list_name) #使用串列list_name建立字典,串列內容會變成字典的鍵,如果沒有設定value值,則用none當值 score.fromkeys(list_name, 'abc') #同上,但是設定每個值都是abc score.get('abc') #搜尋字典的鍵,如果鍵存在則傳回該鍵的值,如果不存在則傳回預設值,如果沒有設定預設值則傳回none #設定預設值的方式(預設值是defaultvalue) score.get('abc', 'defaultvalue') score.setdefault('abc') score.setdefault('abc', 'defaultvalue') #方法和get()相同,不同的地方是如果沒有這個鍵值,就會新增此元素 #沒有設定預設值則傳回none,有設定則依照設定 score.pop(key[, default]) #依照key搜尋,找到就將該元素刪除,同時回傳刪除元素的值,如果沒有找到就傳回default的設定內容,如果沒有設定default則傳回keyError訊息 #建議還是設定default比較好 ----------------------------------------- 範例 #將字典放進串列內,創出50個字典元素,並更改前3個字典的值 sold = [] for i in range(50): solder={'tag':'red', 'speed':'slow', 'order':i} sold.append(solder) for solder in sold[:3]: solder['tag'] = 'green' print(sold[:5]) ----------------------------------------- ``` ```python= #作業13:延續上周 #利用字典的方式,將我們班上的人全部鍵入一個字典內,鍵值是姓名,內容是一個LIST,LIST內容是每個人的考試成績(國語、數學、社會、自然、英語五科) #設計一個輸入框,輸入人名後會搜尋字典內得資料,有找到就出現考試總平均,沒找到就輸出"沒這個人" ``` ### 第15節 * 上週作業解析 * 資料處理8:集合 set * 無序,每個元素都是**唯一**的(有重複時會刪除掉多的,只剩一個) * 集合本身是可變的(可以增減元素),但是元素的內容是不可變的 * 整數、浮點數、字串、元組可當成元素,但是串列、字典、集合等不可以當成元素(會產生錯誤訊號),如果使用set()來建立集合,則可以放串列、字典、集合等元素,但是會將這些元素轉換成集合型元素 * 類別名稱是set * 適用於多項唯一型資料的交叉比對![](https://i.imgur.com/fiSVgmd.png) ``` python A = {1,'abc',('g','h','i')} A = set() #建立集合的方式,用第二種可以建立空集合 A.add(元素) #增加一個元素到集合內 A.clear() #刪除集合所有元素,但集合本身還在,傳回值是none A.copy() #淺拷貝方式Shallow copy複製集合(改變一個集合內容時,另一個不會被改變) A.pop() # 隨機刪除元素,所刪除的元素將被傳回,如果是空集合則傳回錯誤 A.discard(元素) # 刪除特定元素,如果沒有這個元素,也不會出現錯誤訊息 A.remove(元素) # 刪除特定元素,如果沒有這個元素,會出現錯誤訊息 A.difference_update(B[,C,....]) # 刪除A集合內與B集合(或B,C....集合)重複的元素,傳回值是None A.intersection_update(B[,C,....]) # A集合改成B集合(或B,C....集合)的交集(沒交集的元素就刪除),傳回值是None A.symmetric_difference_update(B) # 刪除A集合內有A,B兩集合內都有的元素,並將B集合內沒有出現在A集合的元素加到A集合,和symmetric_difference()結果相同,只是被改變的集合不同 A.update(B[,C,....]) # 將B集合(或B,C....集合)的元素加到A集合中,傳回值是None,兩邊都重複的元素也會出現 -------------------------------------------- 範例 langs = set('DeepBlue Mouton') print(langs) #結果顯示 {'D', ' ', 'p', 'e', 'M', 't', 'u', 'l', 'o', 'n', 'B'} #字串被拆成字母,且重複的會刪除 li = ['apple', 'banana', 'orange', 'apple'] langs = set(li) #也可以寫成 langs = set(['apple', 'banana', 'orange', 'apple']) print(langs) #結果顯示{'banana', 'apple', 'orange'},會刪除重複的 --------------------------------------------- ````` ```python= #作業14: #輸入兩個班級的學生姓名並存入集合中,輸入end就停止 #個別列出兩個班級的學生姓名 #請列出同時在這兩個班級的學生姓名 #請將這兩個班級合併為一班,然後列出來 ``` ### 第16節 * 上週作業解析 * 資料處理9:集合 set ```python ----------------------------------------- 集合的操作 & 交集 intersection() c = A & B c = A.intersection(B) | 聯集 union() c = A | B c = A.union(B) - 差集 difference() c = A - B c = A.difference(B) ^ 對稱差集 symmetric_difference() c = A ^ B c = A.symmertic_difference(B) == 等於 != 不等於 in 是成員 not in 不是成員 ----------------------------------------- A.isdisjoint(B) # 如果兩個集合沒有共同的元素則傳回True,否則傳回False A.issubset(B) # A集合是否是B集合的子集合(B集合的元素是否在A集合全部都有),傳回值是布林值 A.issuperset(B) # A集合的所有元素是否在B集合中都有出現,傳回值是布林值 max(A) #集合內的最大值,如果是字串,則列出unicode碼的最大值 min(A) #集合內的最小值,如果是字串,則列出unicode碼的最小值 sum(A) #集合內數值總和,不可用在字元或字串元素 len(A) # 列出集合元素數量 sorted(A) # 排序集合元素,並將結果存在新的串列物件內,原來的集合不會更動 enumerate(A) # 傳回連續整數配對的enumerated物件 frozenset({'a','b','c'}) #凍結集合,凍結後就不可以再變了,不可以使用add或remove等指令,但可以執行 & | ^ 等集合查詢 ----------------------------------------- 集合操作範例 A = {'a', 'b', 'c'} B = {'c', 'd', 'e'} A & B # {'c'} A | B # {'a', 'b', 'd', 'c', 'e'} A - B # {'a', 'b'} B - A # {'d', 'e'} A ^ B # {'d', 'e', 'a', 'b'} A == B # False A != B # True 'd' in A # False 'd' not in A # True ----------------------------------------- ``` ```python= #作業15: 使用者輸入一個句子,程式判斷是否為全字母句(Pangram,代表一個句子中,英文26個字母都至少出現一次),直到輸入end為止,若程式判斷為全字母句,則列印[此句為全字母句],否則列印[此句不是全字母句] 輸入提示字:請輸入句子以測試是否為全字母句,輸入end結束 提示:使用set(不會重複),如果是全字母句,應該有26個,但是有空白或其他符號的可能,再利用另一個參照用的set來做交集比對 提示:要先轉小寫,避免大小寫被視為不同的字母 ``` ### 第17節 * list、tuple、set(集合)、dict整理比較 ![](https://i.imgur.com/RyLrKKx.png) ```python= zip #可以將幾個可迭代物件(如串列)對應打包為一個新的元組 #如果參數串列的長度不相等,會以最少的數量為準做匹配, ----------------------------- 範例: li=["a","b","c"] li2 = ["AAA","BBB","CCC"] zipdata = zip(li, li2) for i,j in zipdata: print(i,j) #逐一輸出list的對應內容 print(zipdata) #輸出object print(list(zipdata)) #輸出串列及tuple格式 i,j = zip(*zipdata) #將zip拆解開來(解壓縮的感覺),指定給i跟j兩條tuple ------------------------------ ``` ```python= #作業16: 請將之前所有資料格式進行複習,務必熟練 ``` ### 第18節 * 流程控制 * 要注意縮排,整個程式要一致 ``` python if (條件) : 程式 elif (條件) : 程式 else: 程式 #多重條件 if (a > 10 and b > 20) if (a > 10 or b > 20) #作業: #請輸入一個座號,並依據座號判別是哪一組的人員 #1-7號是第一組,8-14是第二組,15-21是第三組, #22-28是第四組,29-35是第五組,超過35號請輸出沒有這個人 #for 重複執行知道次數的 list = [1,2,3,4] for i in list #和下列方法相同 for i in [1,2,3,4] print(i) for i in range(0,1000) print(i) #0是起始值,1000是結束值 #印出0到999,從0開始到end-1,所以是999 for i in range(0,1000,2) #印出0到999,從0開始到end-1,間隔是2 for i in range(500,0,-2) #要遞減時,起始值小於結束值,間隔值為負,從起始值到結束值-1 for i,j in zip([1,2,3], [4,5,6]): print(i,j) #zip 可以一次用兩條序列來跑for迴圈,也可以三條...... #資料組 = [自訂變數 for 自訂變數 in 資料組 if 關係運算式] #用for快速指定Series內容 num_list = [i for i in range(1, 11)] #作業: #請用二行輸出一個list,元素依序是0-400之間的偶數 #作業 #如果要輸出以下的結果,程式要如何寫 # 1 王一 # 2 李二 # 3 趙三 # 4 周四 break #強制跳出這一層for迴圈 continue #符合條件就不執行本次運算,繼續執行下一次重複的計算 #for i in range(20): # if i < 10:continue #輸出的值是超過10的才會輸出 else #一旦for的條件都不能滿足時,就執行else的部分 #for i in range(3): # print(i) #else: # print("over") -------------------------------------------------- 範例: squares = [] n = int(input()) nn = list(range(n+1)) for i in nn: squares.append(i ** 2) print(squares) 可以濃縮成 n = int(input()) square = [num ** 2 for num in range(1,n+1)] print(squares) 尋找質數的範例 n = int(input("輸入數字")) if n == 2: print("%d是質數" % n) else: for i in range(2,n): if n % i == 0: print("%d不是質數" % n) break else: print("%d是質數" % n) -------------------------------------------------- #while 重複執行不知道次數的 i = 0 while i < 8: print(i) i += 1 #印出0到7,主要是重複執行,並判斷條件是否成立(True),成立就繼續,不成立(False)就跳出 #如果設計變成無限迴圈,按Ctrl+C可以中斷 break #強制離開這一層迴圈 continue #符合條件就不執行本次運算,繼續執行下一次重複運算 範例 while True: #這種寫法會一直不斷重複,可搭配break做跳出 選出亂數,遇到特定數字跳出,遇到5的倍數不印出 import random while True: n = random.randint(0,20) if n==11: print("選到11,跳出") break if n%5==0 : continue print(n) 無聊的範例:將list清空 li = ["a","b","c","d"] while li: #重複迴圈,直到li變成空串列 li.pop() #移除最後一個元素 print(li) ``` 作業17 一個正整數,它加上100後是一個完全平方數,再加上168又是一個完全平方數,請問該數是多少? 1、原則:x + 100 = n<sup>2</sup>, x + 100 + 168 = m<sup>2</sup> 2、計算等式:m<sup>2</sup> - n<sup>2</sup> = (m + n)(m - n) = 168 3、設置: m + n = i,m - n = j,i * j =168,i 和 j 至少一個是偶數 4、可得: m = (m + n)+(m - n) = (i + j) / 2, n = (m + n)-(m - n) = (i - j) / 2, i 和 j 要麼都是偶數,要麼都是奇數。 5、從 3 和 4 推導可知道,i 與 j 均是大於等於 2 的偶數。 6、由於 i * j = 168, j>=2,則 1 < i < 168 / 2 + 1。 7、接下來將 i 的所有數字迴圈計算即可。 #作業18: 猜數字1A2B 系統隨機從0-9選4個數字 輸入提示字:請輸入4個數字(數字請勿重複): 如果有重複的字就重猜一次 比對系統選出來的數字,如果數字與位置都對為A,如果數字對但位置不對則為B,如果都沒猜中的就是0A0B 輸出:XXXX:XAXB 重複上列步驟,直到都猜對(4A)為止 輸出:你猜對了:XXXX ### 第19節 * 常用函式 ```python= help(print) #列出print函數的說明 dir(__builtins__) #列出所有內建函數 dir(物件名稱) #列出適用本物件的內建函數 %timeit 執行命令 #可以返回執行該命令幾次,反覆執行幾輪loop,返回執行最快的那一輪的處理時間,顯示出效能 id() #查看變數的位址 lambda #稱為匿名函數,不需要函數名稱的函數 ----------------------------- 範例: vsqu = lambda s:s.replace('g', '') #範例是輸入s,輸出s.replace('g', '') #呼叫 print(vsqu("abcdefgh")) multi = lambda x,y : x*y print(multi(4,2)) print((lambda x,y: x*y)(4,2)) numbers = [50, 20, 2, 18, 4, 36] result = filter(lambda x:x > 10, numbers) # filter() :將list每個元素傳入lambda每個元素傳入Lambda函式進行條件判斷,最後回傳符合條件的元素 print(list(result)) lambda x,y : x if x>y else y 奇特的用法: MAXIMUM = lambda x,y : (x > y) * x + (x < y) * y #將(x > y)如果是false,則視為0,所以0*y = 0,(x < y)如果是True,視為1,則1*x = x a = 10 b = 20 print ('The largar one is %d' % MAXIMUM(a,b)) ------------------------------ map(function, iterable) #会根据提供的函数或指令對串列做映射 #參數1需使用處理用的函數,後面可以放多個迭代(如串列) #列表、元組、字串、字典等都是可迭代物件,可以使用for迴圈遍歷出所有元素的都可以稱為可迭代物件(Iterable) ----------------------------------------- 範例 sq = list(map(lambda x: x ** 2, [1, 2, 3, 4, 5])) print(sq) #輸出[1, 4, 9, 16, 25] #也可以這樣寫 def trip(x): return x ** 2 list1 = [1,2,3,4,5] list1 = list(map(trip, list1)) print(list1) sq = list(map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10])) print(sq) #輸出[3, 7, 11, 15, 19] map(str,li) #列如將串列內的所有元素都改成文字 map(int,li) #列如將串列內的所有元素都改成數字 map(abs,li) #列如將串列內的所有元素都改成正數 map(ord,li) #列如將串列內的所有元素都改成ASCII map(chr,li) #列如將串列內的所有元素都改成字元(ASCII碼對應的) #以上要輸出時容易看的話,要加上list(map(chr,li)) ----------------------------------------- ``` * 作業19 * 撲克牌21點(BlackJack) * 玩家拿兩張明牌,莊家(電腦)拿1張明牌 * 2-10點的牌,以牌面的點數計算,J、Q、K都是10點,A可以記為1點或11點 * 玩家可加牌,以求越接近牌面點數總和21點,也可停止要牌 * 點數超過21點為爆牌,玩家爆牌時就算莊家贏 * 玩家停止要牌且未爆牌後,換莊家加牌,莊家點數如不足17點,則自動加牌到大於等於17點止 * 玩家未爆牌下,莊家爆牌算玩家贏,莊家未爆牌時,看點數,大的人贏 * 流程圖![](https://i.imgur.com/4hpEPvQ.png) * 作業20 * 密碼原則檢查 * 請使用者輸入一個密碼串,其中密碼串須符合以下規則 * 至少含有8個字元 * 只能含有英文和數字 * 至少要有一個大寫英文字母 * 符合上述三項規則,則顯示密碼正確,否則顯示密碼不符 * 輸入範例:請輸入密碼:xxxxxx * 輸出範例:密碼正確 (或密碼不符) ### 第20節 * 自訂函式 function ``` python def 名稱(參數1, 參數2 [,.....]): 程式內容 z = x + y return z #呼叫方式 def 名稱(參數1,參數2="sa"): #將參數設預設值,有預設值的參數2在呼叫時不一定要寫,另外呼叫時也可以指定新的值給參數2 #參數也可以放串列,函式內也可以修訂串列內容,修訂後原串列也會跟著改變 #若是使用關鍵字行參數,呼叫時格式為 參數名稱=值,如 名稱(參數1='A',參數2='B') #以上方式可以在呼叫時只放一個參數1,若 def multivar(*參數): #可以任意輸入1到多個參數 #如果普通參數和任意數量參數並存,必須將任意參數放在()的最右邊 #呼叫方式 multivar('AAA') multivar('aaa','bbb','ccc') #傳進去的參數格式是tuple元組 def multivar(**參數): #使用任意數量的關鍵自行參數,可以自行輸入關鍵字 #此時參數格式為dict字典 #呼叫 multivar(city='AAA',lang='EN',locat='AMR') #同時使用*和**時,順序要注意 def multivar(*參數, **參數): return #傳回資料,並結束函式,return後面的程式碼不會執行 ----------------------------- 範例: def a(var): for i in var: print(i) mb = ["a","b","c"] a(mb) def a(var,g): if g == 1: var.append("dfdf") return var mb = ["a","b","c"] a(mb,1) #函數修改串列後,原串列會跟著改變 #採用以下寫法,原串列不會被改變 a(mb[:],1) ------------------------------ def fname(1, 3) def fname(參數2="a",參數1="b") #此方式可以讓參數的位置亂跳,但參數名稱需配合def後面的參數名稱 #有預設值得參數放後面,這樣呼叫時比較不會有順位的錯誤 def fname(參數1,參數2): return 參數1-參數2 #回傳參數設計,回傳參數可以不只一個,用,分開 #如果沒有設定回傳值(return),則參數會預設傳回None #回傳值可以是數值、字串、字典等 #用一個變數來接收回傳值 ----------------------------- 範例: def fname(參數1,參數2): return 參數1+參數2,參數1-參數2,參數1*參數2,參數1/參數2 #呼叫 add, sub, mul, div =fname(20,10) ------------------------------ 遞迴式函數設計 #每次呼叫自己時,會讓使用範圍越來越小 #必須有一個終止條件 ----------------------------- 範例: def fact(n): if n == 1: return 1 else: return (n*fact(n-1)) #產生階乘運算(例如fact(5) 回傳1*2*3*4*5的值) ------------------------------ ``` * 作業21 * 請使用函示撰寫 * 企業發放的獎金根據利潤來計算,並依據獎金的金額分成不同部分處理。利潤(I)低於或等於10萬元的部分,獎金可發放10%;利潤高於10萬元,低於20萬元之部分,獎金可發7.5%;利潤20萬到40萬間,獎金發放5%;40萬到60萬之間,獎金發放3%;60萬到100萬之間,獎金發放1.5%,超過100萬元的部分按1%發放,從鍵盤輸入當月利潤I,求應發放獎金總數? * 範例輸入 利潤:700000 100000 * 0.015 = 1500.0 200000 * 0.03 = 6000.0 200000 * 0.05 = 10000.0 100000 * 0.075 = 7500.0 100000 * 0.1 = 10000.0 總獎金是 35000.0 * 作業22 * 使用者可以不斷輸入整數,以輸入之整數當作參數呼叫primeTest()函式,此函式回傳字串顯示質數或非質數,直到使用者輸入-9999結束測試 * 負數為非質數 * 輸入提示字:請輸入整數: * 輸出提示:a為非質數 或 a為質數 * 作業23 * 使用者輸入兩個整數a,b,當作參數呼叫gcd()函式,並回傳兩數的最大公因數 * 輸入提示字:請輸入兩個數,中間以逗點做分隔:52,91 * 輸出提示字:52與91的最大公因數為13 * 使用輾轉相除法 * 遞迴呼叫 ### 第21節 * random隨機數模組 * [https://docs.python.org/zh-tw/3/library/random.html](https://docs.python.org/zh-tw/3/library/random.html) ```python= import random random.randint(min, max) #可以產生min與max之間的整數值,結果包含min和max random.choice(list) #可以在list串列中隨機取一個元素 random.choice("abcde") #隨機從abcde選1個字母 random.choice(range(5,10)) #隨機從5-9中選1個數字 random.randrange(start, end, step) #產生start到end中間,間隔為step的隨機整數 ``` ### 第22節 * 類別 (物件導向) * 類別中包含屬性(attribute)和方法(method) * 類別中的方法是時就是自訂函數,但只有屬於該類別的物件可以調用,其他地方不能用 * 類別中參數可以直接用該名稱調用,但是要自訂一個新的變數時,需要加上self ``` python -------------------------------------------------- 範例: #基礎類別宣告與調用 class cy(): #cy後面的()也可以省略 title='OO國小' def sname(n): return n #調用 print(cy.title) print(cy.sname("AAA")) -------------------------------------------------- #初始化類別的method,指宣告這個類別物件時,將自動執行這個方法,又稱建構元constructor,負責物件的初始化 __init__() #建構函式,負責初始物件的建立 __new__() -------------------------------------------------- 範例: class cy(): def __init__(self,uname,money): self.name = uname self.balance = money self.title="taipei Bank" print(self.name) print(uname) def pd(self): print(self.name) #調用 bcla = cy("白先生",100) print(bcla.title) #也可以這樣用,直接呼叫,不用指定給變數 cy("白先生",100) cy("白先生",100).add() #呼叫類別時,會自動執行init方法,參數「白先生」會傳給init的uname,100會傳給money #init的self是必須的,也必須放在所有參數最前面,初始化類別時會自動傳入這個參數,代表的是類別本身的物件 #未來在類別內想要參照各屬性與函數執行運算皆使用self #此為公有屬性,可以在外部調用 #範例2 #list搭配class class Cat2: def __init__(self, name, age, color): self.name = name self.age = age self.color = color cats = [ Cat2(input("請輸入寵物名1="), input("請輸入age="), input("請輸入color=")), Cat2(input("請輸入寵物名2="), input("請輸入age="), input("請輸入color=")), Cat2(input("請輸入寵物名3="), input("請輸入age="), input("請輸入color=")), ] #逐一列出各項資料 #如果使用print(cats),會返回[<__main__.Cat2 object at 0x0000024D31BB0160>, <__main__.Cat2 object at 0x0000024D31BB0220>, <__main__.Cat2 object at 0x0000024D31BB0250>] for key in cats: print("名",key.name) print("年紀",key.age) print("毛色",key.color) -------------------------------------------------- ``` ```python= #作業:密碼產生器 #2人1組 #第1人撰寫一個class,可傳入1個引數,引數可隨意輸入超過8個字的數字,然後抽取出其中的偶數位數,並組成1個list傳出來 #第2個人撰寫一個class,可傳入1個引數,引數為第1個人傳出來的list,將這個list重新組合為1個數字,並轉換為16進位後傳出來 #每個人撰寫好從成.py檔案,用一個新的檔案,使用from 檔案名 import class名 的方式導入前面兩個class,並產生密碼 ``` * 屬性 * 類別內的屬性可以讓外部引用的稱為共有屬性,可以讓外部引用的方法稱為公有方法,公有屬性可以在類別外修改 * 私有:無法在類別外修改私有類別屬性,也無法在類別外呼叫的私有方法 ```python= 範例: class cy(): def __init__(self,uname,money): self.__name = uname self.__balance = money self.__title="taipei Bank" print(self.__title) #私有屬性 def __rcate(self,ud): print(ud) #私有方法,僅可以在類別內部被呼叫 def tod(self,rd): self.__rcate(rd) #呼叫私有方法__rcate,並傳入rd參數 #調用 bcla = cy("白先生",100) bcla.tod(123) #類別內的屬性宣告時加上__即可變成,外部就無法修改了,外部也無法調用 #以上例子如果直接呼叫bcla.__name會報錯,如果呼叫bcla.__rcate("text")也會報錯 #需要改成def rcate()這樣才可以呼叫 ``` * 繼承 * 被繼承的類別稱為父類別(parent class)或基底類別(base class) * 繼承的類別稱為子類別(child class)或衍生類別(derived class) * 優點是許多父類別的公有屬性或方法,在子類別中可以直接引用,另外子類別也可以有自己的屬性與方法 * 基底類別必須在衍生類別前面 * 衍生類別要取得基底類別的私有屬性,只能在基底類別使用return的方式將私有屬性包在方法內被呼叫 * 衍生類別也可以有自己的__init__方法,如果衍生和基底類別的方法或屬性名稱重複,會先使用衍生類別的,不行時再使用基底類別的 ```python= -------------------------------------------------- 範例: class cy(): def __init__(self,uname,money): self.__name = uname self.__balance = money self.title="taipei Bank" class shi(cy): #繼承cy類別的屬性及方法 pass #pass就是不做任何事情,只是為了維持結構完整,逐步開發程式時常用 #調用 bcla = shi("白先生",100) print(bcla.title) ----------------------------------------------- ``` * 衍生類別使用基底類別方法 * super() 可以繼承父類別的所有屬性及方法 ```python= ----------------------------------------------- 範例: class A(): def __init__(self, aname, aage): self.name = aname.title() self.age = aage print(self.name, self.age) class B(A): #繼承基底類別A def __init__(self,bname,bage): super().__init__(bname,bage) #使用A列別的init方法,變數不用加self. #直接將變數傳給A類別的init方法處理 #加上super()可以繼承A類別的所有屬性及方法 class A(): def plus(self, x): y = x+1 print(y) class B(A): def add(self, x): super().plus(x) ga = A() ga.add(6) ``` ```python= #作業:電子時鐘 #以類別的方式設計一個電子計時時鐘 #可以手動輸入起始的時分秒 ``` ![](https://i.imgur.com/CVpRnEI.png) ```python= 三層的使用: class A(): def __init__(self): self.Aname = "AAA" def get_info1(self): print('A class is', self.Aname) class B(A): #繼承A類別 def __init__(self): self.Bname = "BBB" super().__init__() # 將A類別的init複製,B類別就有A類別的屬性 def get_info2(self): print('B class is', self.Bname) class C(B): #繼承B類別 def __init__(self): self.Cname = "CCC" super().__init__() # 將B類別的init複製,C類別就有A跟B類別的屬性,若是方法method就不需要用這個,直接繼承 def get_info3(self): print('C class is', self.Cname) tt = C() tt.get_info1() 旁枝的使用 class A(): def __init__(self): self.Aname = "AAA" class BA(A): #繼承A類別 def __init__(self): self.Bname = "BBB" super().__init__() # 將A類別的init複製 class CA(A): #繼承A類別 def __init__(self): self.Cname = "CCC" super().__init__() # 將A類別的init複製 def get_info(self): print("A name is",self.Aname, "\n B name is",BA().Bname, #取得旁枝BA類別的屬性,記得加上() "\n C name is",self.Cname) tt = CA() tt.get_info() 多重繼承 class A(): def __init__(self): self.name = "FA" def info1(self): self.Aname = "Aname" print("A") class BA(A): #繼承A類別 def info2(self): self.BAname = "BAname" print("BA") class CA(A): #繼承A類別 def __init__(self): super().__init__() # 將A類別的init複製 def info3(self): self.CAname = "CAname" print("CA") class DBC(BA,CA): #同時繼承BA跟CA類別 def __init__(self): super().__init__() # 將CA類別的init複製,同時可擁有A類別的init屬性 self.DBCname = "DBCname" def info4(self): print("DBC") t = DBC() print(t.DBCname) t.info1() print(t.name) -------------------------------------------------- isinstance(物件, 類別) #查詢物件是否屬於該類別,是的話返回True #有繼承時,子類別的物件屬於父類別時(True),但父類別的物件並不一定屬於子類別 -------------------------------------------------- 依上面範例: isinstance(t,DBC) #返回True isinstance(t,A) #返回True,有繼承關係 Y = CA() isinstance(Y,DBC) #返回False,繼承關係是從上到下,下屬于上,上不屬於下 -------------------------------------------------- ``` --- * 特殊方法 ``` python __doc__ #列出文檔內的 ''' ''' 標示的註解 __name__ #判斷程式是自己執行或是被import當成模組使用 #自己執行時,__name__ = __main__ #當成模組使用時,輸出模組名稱 __str__() #可以協助返回較容易讀取的字串 -------------------------------------------------- 範例: class name: def __init__(self,bn): self.name = bn def __str__(self): #定義返回容易閱讀的字串 return self.name t = name("Hang") print(t) #有__str__返回 Hang #沒有__str__返回 <__main__.name object at 0x10e5340d0> -------------------------------------------------- __repr__() #和__str__方法相同,因為單純在python Shell,系統會呼叫shell做回應 #可以在class內寫上 __repr__ = __str__ __iter__() #將類別設計成迭代物件(類似list),提供for使用,會搭配next()及raise Stoplteration -------------------------------------------------- 範例: class Fib(): def __init__(self,max): self.max = max def __iter__(self): self.a = 0 self.b = 1 return self def __next__(self): fib = self.a if fib > self.max: raise StopIteration self.a, self.b = self.b, self.a + self.b return fib for i in Fib(100): print(i) -------------------------------------------------- ``` ### 第23節 * 檔案處理 * 使用os或os.path模組 ```python os.getcwd() #取得現在的所在目錄 os.path.abspath(檔名) #取的檔案的絕對路徑 -------------------------------------------------- 範例: print(os.path.abspath('.')) #目前所在資料夾的絕對路徑 print(os.path.abspath('..')) #目前所在位置的上一層資料夾絕對路徑 print(os.path.abspath('Untitled1.ipynb')) #該檔案的絕對路徑 -------------------------------------------------- os.path.relpath(path, start) #傳回從start(檔案或位置)到path的相對路徑清單 #若start省略,則傳會工作目錄到path間的相對路徑清單 #anaconda並不會正確顯示 os.path.basename(path) #去除目錄的路徑,回傳檔案名稱(包含附檔名) os.path.exists(path) #path的檔案或資料夾如果存在傳回True,否則傳回Fase os.path.isabs(path) #path的檔案或資料夾是絕對路徑傳回True,否則傳回Fase(mac根目錄前要加上/,例如/Users/ycp/Desktop/質因數.ipynb) os.path.isdir(path) #path是資料夾傳回True,否則傳回Fase,(path要用絕對路徑) os.path.isfile(path) #path是檔案傳回True,否則傳回Fase os.mkdir(path) #建立path的目錄,建議搭配os.path.exists檢查目錄是否已存在 os.rmdir(path) #刪除path目錄,限制只能是空的目錄 os.remove(path) #刪除path檔案 os.chdir(path) #切換目前工作資料夾到path os.path.join(參數1, 參數2, 參數3,......) #將參數內的字串結合成一個檔案路徑 os.path.getsize(檔名) #取得檔案的大小,單位是位元組 os.listdir() #以串列方式列出該目錄的內容 os.walk(path) #列出該path之下所有的檔案和資料夾(目錄數) #返回迭代物件,每一個包含3個值:工作目錄名稱(字串),該工作目錄下所有的子目錄(串列),,該工作目錄下所有的檔案(串列) -------------------------------------------------- 範例: import os for dirname, subd, fname in os.walk('finlab_course/'): #for 後面的順序不可以亂,但名稱可以自取 print("工作目錄名稱:",dirname) print("子目錄名稱串列",subd) print("檔案串列",fname) -------------------------------------------------- ``` * 關於檔案的常用函數(不用引入os) ```python open(file_path, mode="r") open(file_path, "w") open(file_path, "w", encoding="utf-8") #file_path:檔案的路徑,有絕對路徑跟相對路徑兩種 #相對路徑: ..\dataFile\read.txt # . 代表目前目錄 .. 代筆上一層目錄 #路徑檔名如果是C:\mydocumt\myfile.txt,為了抵銷\的逸出字元效果,請寫成C:\\mydocumt\\myfile.txt #開啟一個檔案,mode有不同開啟選項,不寫就是r #如果檔案不存在,又是w模式,則open會建立該檔案,若檔案存在,則會清空該檔案 #r讀取,w覆蓋式寫入,a附加式寫入,x開啟一個新的檔案提供寫入(如果檔案已經存在會產生錯誤) #b開啟為檔案模式,t開啟文字檔案模式,+開啟檔案供更新用 #微軟系統的ANSI編碼為cp950(encoding="950") #encoding = "utf-8-sig" 採用LE的BOM編碼系統 # http://mt116.blogspot.com/2017/08/coding-system-unicode.html read() #讀取檔案內容 readline() #讀取一行內容 readlines() #逐行讀取檔案內容,以串列方式儲存,每行的換行字元皆會儲存在串列內 close() #關閉檔案,如果沒有關閉檔案,可能資料會遺失 with open(file_path,"r",encoding="utf-8") as 檔案物件 : #此方法也可檔案物件,但是可以不必關閉檔案,系統會在跳出with區塊時自動將檔案關閉 find(字串) #搜尋字串是否有在目標字串內,回傳找到的索引位置(從0開始) write(輸出的資料) #輸出資料寫入到檔案內,無法寫入數值資料,要寫入資料請將數值轉字串 #輸出多行資料,請逐行寫write,如果要斷行請在每行最後加上\n #如果搭配readlins(),其形態為串列時,需搭配join #範例:foj.write( "".join(data)) data是list格式,代表用空字串將list的所有元素串接成一個字串型態 ----------------------------- 範例: file_obj = open('test.html') data = file_obj.read() file_obj.close() print(data) #可以改寫如下 with open('test.html') as file_obj: data = file_obj.read() print(data) #逐行讀取檔案內容 with open('test.html') as file_obj: for i in file_obj: print(i) #另一種寫法 objlist = file_obj.readlines() #readlines之前不可以有read,不然讀不出來 print(objlist) #搜尋數據 a = "abcd" b = "c" if b in a: print("ok") #或是使用 index = a.find(b) if index >= 0: print("ok") #數值寫入檔案的方法 with open('test.html') as file_obj: file_obj.write(str(100)+'\n') file_obj.write("ABC") ----------------------------- ``` * 使用glob模組 ```python import glob glob.glob #獲得特定資料夾的的內容,返回串列 #可以使用萬用字元* -------------------------------------------------- 範例: glob.glob('/Users/ycp/Desktop/*') glob.glob('*.txt') glob.glob('Untitled*.ipynb') -------------------------------------------------- ``` * 使用shutil模組 * 檔案或目錄的複製、刪除、更動位置、更改名稱 ```python import shutil shutil.copy(source, destination) #檔案複製,複製時source檔一定要存在 shutil.copytree(source, destination) #目錄複製,複製時source目錄一定要存在,複製時連同裡面的資料也會複製 shutil.move(source, destination) #檔案移動,移動時source檔一定要存在,移動後,source檔案不再存在,source跟destination的名稱不一定要相同 #也可以用來改檔名或目錄名 #也可以移動目錄,移動時連同該目錄下的子目錄也會一並移動 #移動目錄時也可以同時改名 shutil.rmtree(目錄名稱) #刪除底下有資料的目錄,刪除就是刪除,不會在垃圾桶 -------------------------------------------------- 範例: import shutil shutil.move("t2.txt", "./gg") #移動t2.txt到同位置的gg子目錄內,寫成.//gg亦可 shutil.move("t2.txt", "t3.txt") #更改檔案名稱 -------------------------------------------------- ``` * 使用send2trash模組 ```python import send2trash send2trash.send2trash(目錄名稱) #刪除底下有資料的目錄,刪除後會在垃圾桶 ``` * 使用zipFile模組 * 檔案或目錄壓縮或解壓縮 ```python import zipfile fz = zipfile.ZipFile("dn.zip", "w") #先建立物件,fz是物件名稱,dn.zip是未來輸出的zip檔 # w 代表未來是供write方法寫入 # zipfile()無法執行整個目錄直接壓縮,因此採用迴圈方式逐一寫入zip檔 namelist() #傳回zip檔案內所有被壓縮的檔案或目錄名稱,以串列方式傳回此物件 infolist() #搭配namelist(),傳回個元素的屬性,檔案名稱filename,檔案大小file_size,壓縮結果大小compress_size,檔案時間date_time extractall() #解壓縮zip檔 -------------------------------------------------- 範例: import zipfile,glob,os with zipfile.ZipFile('archive.zip', 'w') as zf: for i in glob.glob("/Users/ycp/Desktop/t*"):#逐一處理gg資料夾的所有檔案 zf.write(i, os.path.basename(i), zipfile.ZIP_DEFLATED) # zipfile.ZIP_DEFLATED 是壓縮方式 zf.close #關閉物件 #讀取壓縮檔案內檔案的各項屬性 import zipfile listfile = zipfile.ZipFile("archive.zip", "r") print(listfile.namelist()) #以串列方式列出檔案名稱 for i in listfile.infolist(): print(i.filename, i.file_size, i.compress_size, i.date_time) #逐一列出各項屬性 #解壓縮zip檔案 listfile = zipfile.ZipFile("archive.zip") listfile.extractall('out') #解壓縮後的資料夾名稱 listfile.close -------------------------------------------------- ``` * 使用pyperclip剪貼簿模組 ```python pip install pyperclip #安裝模組 -------------------------------------------------- 範例: import pyperclip pyperclip.copy("AAA") #將字串拷貝到剪貼簿 string = pyperclip.paste() #將剪貼簿拷貝回string print(string) -------------------------------------------------- ``` ### 第24節 #### time時間模組 ```python= import time time.time() #傳回從1970年1月1日00:00:00AM到現在的秒數 time.sleep(秒數) #讓工作暫停該秒數值 time.asctime() #列出目前系統時間 time.localtime() #返回目前時間的結構資料,結構可以索引的方式取得內容 #索引值可以print出來看,參數[0]是年,其他類推 #星期資料(參數[6])中0代表星期一,1是星期二,其他類推 #參數[7]代表是一年中的第幾天 #參數[8]是夏令時間,0代表不是,1代表是 ``` --- ##### datetime時間模組 * [說明文件](https://docs.python.org/zh-tw/3/library/datetime.html) * [參考文件](https://codertw.com/%E7%A8%8B%E5%BC%8F%E8%AA%9E%E8%A8%80/179287/) * 常量 * datetime.MINYEAR date和datetime物件允許的最小年份 * datetime.MAXYEAR date和datetime物件允許的最大年份 * 類 * datetime.date 日期物件,屬性(year, month, day),公曆1年1月1日被稱為第一天,依次往後推 * datetime.time 時間物件,屬性(hour, minute, second, microsecond, tzinfo),表示一個(當地)時間物件,與任何特定的日期無關,並且可以通過tzinfo(時區)物件進行調整 * datetime.datetime 日期時間物件,屬性(date和time屬性組合),包含date物件和time物件的所有資訊 * datetime.timedelta timedelta物件表示一個時間段,即兩個日期 (date) 或日期時間 (datetime) 之間的差。支援引數:weeks、days、hours、minutes、seconds、milliseconds、microseconds * datetime.tzinfo 時區資訊物件的抽象基類, datetime和time類使用它定製化時間調節 ```python= import datetime from datetime import datetime,date,time #從datetime中導入datetime類和date類,加上這一行,後面呼叫時只要用date.XXXXX即可,沒有加上這一行,只有import datetime時,後面呼叫要用datetime.date.XXXX date.today() # 返回當前日期物件 date.fromtimestamp(1491448600) # 返回時間戳的日期物件 date.fromordinal(1) # 返回對應公曆day序數的日期物件,如參數為1時,返回0001-01-01,參數為2時,返回0001-02-01 d = date(2017,4,6) #輸入參數設定為日期型態 d.year #返回date物件的年份,型態為int d.month # 返回date物件的月份,型態為int d.day # 返回date物件的日,型態為int d.timetuple() # 返回date物件的struct_time結構,如本例輸出 time.struct_time(tm_year=2017, tm_mon=4, tm_mday=6, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=96, tm_isdst=-1) d.toordinal() # 返回公曆日期的序數,就是從0001-01-01開始計算到今天的天數,以day為單位 d.weekday() # 返回一星期中的第幾天,星期一是0,星期日為6 d.isoweekday() # 返回一星期中的第幾天, 星期一1,星期日為7 d.isocalendar() # 返回一個元組(年份, 這一年的第幾周, 周幾),周幾:星期一為1 d.isoformat() # 以ISO 8601格式‘YYYY-MM-DD’返回date的字串形式 d.ctime() # 返回一個表示日期的字串,如本例返回'Thu Apr 6 00:00:00 2017' d.strftime("%Y-%m-%d") # 返回指定格式的日期字串 d.replace(year=2012, month=12, day=12) # 替換,中間的參數不一定要全寫,想換哪個寫哪個 t = time(12, 10, 30, 50) #輸入參數設定為時間型態,參數依序為時,分,秒,微秒 t.hour # time物件小時數 t.minute # time物件分鐘數 t.second # time物件秒數 t.microsecond # time物件微秒數 t.isoformat() # 返回ISO 8601格式的時間字串,本例返回'12:10:30.000050' t.strftime("%H:%M:%S:%f") # 返回指定格式的時間字串 t.replace(hour=23, minute=0, second=0, microsecond=1000) # 替換,中間的參數不一定要全寫,想換哪個寫哪個 datetime(2021, 12, 15) #將參數改為datetime物件輸出 datetime.datetime(2021, 12, 15, 0, 0) 或 2021-12-15 00:00:00 datetime(2021, 12, 15, 17, 30) #輸出 datetime.datetime(2021, 12, 15, 17, 30) 或 2021-12-15 17:30:00 datetime.today() # 返回本地當前的時間datetime物件 datetime.now() #返回本地當前的日期和時間的datetime物件 #輸出 2021-07-04 19:46:25.422267 datetime.date(datetime(2021,5,3)) #取得特定日期(沒有時間) #輸出 datetime.date(2021, 5, 3) 或 2021-05-03 datetime.now().date() #取得本地現在的日期 datetime.now().time() datetime.time(datetime.now()) #取得本地現在的時間 datetime.utcnow() # 返回當前UTC日期和時間的datetime物件 datetime.fromtimestamp(1491468000) # 返回對應時間戳的datetime物件 datetime.fromordinal(699000) # 同date.fromordinal類似,返回結果多了時和分 datetime.combine(date(2012, 12, 12), time(23, 59, 59)) # 拼接date和time,如本例返回2012-12-12 23:59:59 datetime.strptime("string", 'format') #將字串格式轉為時間格式 #datetime.strptime('2017/1/1', '%Y/%m/%d %H:%M:%S %p') #格式: # %Y 4位數西元年份 %y 2位數年份,西元年後兩位 # %m 月份(1-12) %B 月份名稱(如January) # %A 星期名稱(如Sunday) # %d 日期(1-31) # %H 24小時(0-23) %l 12小時(1-12) # %p AM或PM %M 分鐘(0-59) # %S 秒(0-59) d = datetime(2017, 4, 6, 12, 10, 30) d.date() # 從datetime中拆分出date d.time() # 從datetime中拆分出time d.timetz() # 從datetime中拆分出具體時區屬性的time d.replace(year=2016) # 替換,參數可以參考前面的replace參數設定 d.timetuple() # 時間陣列,即struct_time結構,如本例返回time.struct_time(tm_year=2017, tm_mon=4, tm_mday=6, tm_hour=12, tm_min=10, tm_sec=30, tm_wday=3, tm_yday=96, tm_isdst=-1) d.toordinal() # 返回公曆日期的序數,就是從0001-01-01開始計算到今天的天數,以day為單位 d.weekday() # 返回一星期中的第幾天,星期一是0,星期日為6 d.isoweekday() # 返回一星期中的第幾天, 星期一1,星期日為7 d.isocalendar() # 返回一個元組(年份, 這一年的第幾周, 周幾),周幾:星期一為1 d.isoformat() # 返回ISO 8601格式的時間字串,本例返2017-04-06T12:10:30 d.ctime() # 返回一個表示日期的字串,如本例返回'Thu Apr 6 12:10:30 2017' d.strftime('%Y/%m/%d %H:%M:%S') # 返回指定格式的日期字串,將時間格式轉成字串格式 d = date.today() d - timedelta(days=5, hours=5) # 今天日期減5天5小時的日期,參數可自由選用 ``` * datetime、date、time 都提供了 strftime() 方法,該方法接收一個格式字串,輸出日期時間的字串表示。支援的轉換格式如下: %a 英文星期的簡寫 Sun, Mon, …, Sat %A 英文星期的全拼 Sunday, Monday, …, Saturday %w 星期幾,星期天為0,星期六為6 0, 1, …, 6 %d 這個月的第幾天,以0填充的10進位制 01, 02, …, 31 %b 月份英文簡寫 Jan, Feb, …, Dec %B 月份英文全拼 January, February, …, December %m 月份數,以0填充的10進位制 01, 02, …, 12 %y 不帶世紀的年份 00, 01, …, 99 %Y 帶有世紀的年份 1970, 1988, 2001, 2013 %H 24小時制的小時數 00, 01, …, 23 %I 12小時制的小時數 01, 02, …, 12 %p AM或者PM AM, PM %M 分鐘 00, 01, …, 59 %S 秒數 00, 01, …, 59 %f 微秒 000000, 000001, …, 999999 %z 與utc時間的間隔 (), 0000, -0400, 1030 %Z 時區 (), UTC, EST, CST %j 當年的第幾天 001, 002, …, 366 %U 當年的第幾周(星期天作為周的第一天) 00, 01, …, 53 %W 當年的第幾周(星期一作為周的第一天) 00, 01, …, 53 %c 日期時間的字串表示 Tue Aug 16 21:30:00 1988 %X 時間字串表示 21:30:00 %x 日期字串表示 08/16/88 %% 相當於轉意等於一個% % ### 第25節 * 程式錯誤(異常)處理與LOG紀錄 * 一般程式有錯誤或異常時,會印出錯誤訊息,並停止程式繼續執行,使用異常處理時,有捕捉到異常資訊時,會執行異常處理部分的指令,和後跳過異常的那一行繼續執行下一行 * https://docs.python.org/zh-tw/3/library/exceptions.html * 錯誤說明: * AttributeError 通常指物件沒有這個屬性 * Exception 執行中發生中斷執行而結束者,稱為異常,一般錯誤皆可使用,可以提供捕捉各種基礎異常用 * FileNotFoundError 找不到檔案 * IOError 在輸入或輸出時發生錯誤 * IndexError 索引超出範圍區間 * KeyError 在映射中沒有這個鍵 * MemoryError 需求記憶體空間超出範圍 * NameError 物件名稱未宣告或賦值 name 'a' is not defined * SyntaxError 語法錯誤 * SystemError 直譯器的系統錯誤 * TypeError 資料型別錯誤(例如把數字和文字相加時會發生) * ValueError 傳入無效參數 * ZeroDivisionError 除數除以0的錯誤 ```python= #基本模式 try: 可能會發生異常的程式碼 except: 發生異常要執行的程式碼 #except 後面可以加上特定的錯誤型態,如果不寫,就是只要有異常就會執行本段程式碼 else: 沒有發生異常要執行的程式碼 範例 def division(x, y): try: return x/y #指令或處理程序 except ZeroDivisionError: # 捕捉到異常 print("除數不可以為0") # 異常時執行此列 #回傳一個None finally: print("階段任務完成") #finally不一定要寫 #有寫時,這個try之下一定會執行finally #在def之下,如果無誤會先回傳finally內容,再傳回try,如果有異常,先執行except,再執行finally,最後返回主程式輸出None print(division(10,2)) # 參數無誤,執行return x/y print(division(5,0)) # 除數為0,執行異常處理程序 print(division(6,2)) #上一行錯誤跳過後繼續處理這一行 #將上面的改寫成: #增加程式的可讀性 def division(x, y): try: ans = x/y #先處理此程序 except ZeroDivisionError: # 捕捉到異常 print("除數不可以為0") # 異常時執行此列 else: return ans #如果無誤執行此程序 #分析檔案開啟錯誤 fn="test.txt" try: with open(fn) as file_obj: data = file_obj.read() except FileNotFoundError: print("找不到%s檔案"%fn) except TypeError: #可以設定不只一個錯誤捕捉 print("資料型別錯誤") except (FileNotFoundError, TypeError): #一個except同時捕捉多的錯誤 print("有錯誤") else: wordnum = data.split() print("字數:", len(wordnum)) #使用內建的錯誤訊息 def division(x, y): try: return x/y except ZeroDivisionError as e: # 使用python內建異常或錯誤訊息 print(e) #捕捉所有異常 def division(x, y): try: return x/y except: print("有異常") #會回傳一個None ``` * 自行定義抹些狀況為異常,丟出異常訊息,程式停止往下執行,同時讓程式跳到自行設計的except去執行 ```python raise exception("自訂的錯誤訊息") ...... try: 指令 except Exception as err: #err是任意取名的變數,內容就是raise exception後面的訊息 指令 #範例 try: a = input("請輸入數字") if (not a.isdigit()): raise ValueError('必須是數字') except ValueError as err: print('引發異常',repr(err)) #範例 #當在沒有引發過異常的程序使用無參的raise語句時,它默認引發的是RuntimeError異常 try: a = input("輸入一個數:") if(not a.isdigit()): raise except RuntimeError as e: print("引發異常:",repr(e)) #範例,搭配traceback模組將錯誤資訊記錄在檔案中 import traceback def passwd(pwd): pwdlen = len(pwd) if pwdlen < 5: raise Exception("密碼長度不足") if pwdlen > 8: raise Exception("密碼長度太長") print("密碼長度正確") try: passwd("aabbccdd") except Exception as err: errlog = open("errlog.txt","a") errlog.write(traceback.format_exc()) #寫入錯誤資訊內容 errlog.close() print(err) assert 條件, '字串' #程式檢查點 #程式執行至此,需滿足條件(True),才可以繼續執行 #如果執行無法滿足條件(False),程式會泡出異常,並印出後面的字串 for i in range(100): assert i<=20 ,'i大於20' print(i) #讓系統停止assert運作 #找到phthon.exe(windows下)存放的資料夾,在cmd模式下,切換到該資料夾,並輸入 # python.xe -O D:\pdata\ch12.py # -O 後面是指要執行中斷assert的程式路徑 ``` * 程式LOG * logging模組5個等級(上到下。由小到大) * DEBUG:顯示最低層級的內容 * INFO:紀錄一般發生的事件 * WARNING:顯示的內容不會影響程式執行,但未來可能導致問題發生 * ERROR:程式在某些狀態引發錯誤的原因 * CRITIAL:通常顯示將會讓整個系統當掉或中斷的錯誤 ```python import logging #使用下列函數設定顯示資訊的等級,為來只有此等級或更高等級的LOG會被顯示 lgooing.basicConfig(level=logging.DEBUG) #DEBUG等級 #指令 logging.debug('字串') logging.info('字串') logging.warning('字串') logging.error('字串') logging.critical('字串') #印出的結果會有前導訊息,如 DEFUB:root: lgooing.basicConfig(level=logging.DEBUG, format=' ') #加上 format=' ' 可以取消前導訊息 lgooing.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s : %(message)s') #訊息前面加上紀錄時間及顯示層級 #anaconda中,若level有修改,要restart kernel才會正確顯示 logging.basicConfig(filename='logout.txt', level=logging.DEBUG, format='%(asctime)s - %(levelname)s : %(message)s') #filename可以將log存在檔案內,但此時螢幕就不會出現log訊息 #重複執行時,後面的log會在檔案接下去寫入 #須參考層級,如果低於設定的level,也不會存入檔案內 範例: import logging logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s : %(message)s') logging.debug('程式開始') for i in range(5): logging.debug('目前索引 %s' %i) logging.debug('程式結束') logging.disable(level) #停用log,level是指層級 logging.disable(logging.CRITIAL) ``` ### 第26節 * 正規表達式 Regular Expression * 使用 re 模組 * https://docs.python.org/2/library/re.html * 規則說明: * \d 表示0-9數字字元 * \d+ 表示不限長度的數字(使用+,其他規則類推) * \D 除了0-9之間的整數字元以外的其他字元 * \s 空白、定位、Tab鍵、換行、換頁字元 * \S 除了空白、定位、Tab鍵、換行、換頁字元之外的其他字元 * \w 數字、字母和底線_字元[A-Za-z0-9_] * \W 除了數字、字母和底線_字元[A-Za-z0-9_]之外的其他字元 * | 或者 'mary|john' 表示mary或john皆符合,字串周邊不可以有空格 * (字串?) ()內的可有可無,皆算符合 (\d?) * (字串*) ()內的字串出現0到多次皆符合 (\w*) * (字串+) ()內的字串出現1到多次皆符合,和*不同的是至少要有1次,否則回傳None (\s+) * \d{4} 4個數字,{}內是重複次數 * 字元分類形式,[ ]內不需使用\ * [a-z] 搜尋a-z的小寫字元 * [A-Z] 搜尋A-Z的大寫字元 * [aeiouAEIOU] 搜尋aeiouAEIOU這10個字元 * [2-5.] 搜尋2-5的數字和 . (在[]內不用寫成\.) * [^ ] []加上^,搜尋不在[]內規則的所有字元 * '^字串' ''前面加上^,表示搜尋的字串必須出現在被搜尋字串的起始位置才算成功 * '字串$' ''後面加上$,表示搜尋的字串必須出現在被搜尋字串的最後位置才算成功 * '^字串$' 前後都加,被搜尋的句子一定只有一個字串 * '.字串' .是萬用字元,代表除了換行字元之外的所有字元,但是只有一個字元(搜尋符號.要使用\.) * '.' 搜尋所有字元,換行字元除外 * re.DOTALL 可以搜尋包括換行字元,放在search(),findall(),compiler()的Flags位置 * re.VERBOSE 可以在pattern規則內分行時加上註解 * re.I 或是 re.IGNORECASE 忽略字母大小寫 ```python= import re word = r'\d\d\d\d-\d\d\d-\d\d\d' #定義規則 ckrule = re.compile(word) #建立規則物件 # ckrule = re.compile(r'\d\d\d\d-\d\d\d-\d\d\d') msg1 = "我的電話是0932-321-123" msg2 = "我有兩隻電話:0955-234-543,0977-778-543,你保留一下" for i in range(1,3): pnum = ckrule.search(locals()['msg%s'%i]) # pnum = ckrule.search(locals()['msg{}'.format(i)]) #使用search搜尋字串中符合的規則的 # locals()['msg%s'%i]是動態設定變數名稱msg1,msg2 #search只會找到第一組相符的,第二組以後的不會找 #回傳格式 <re.Match object; span=(5, 17), match='0932-321-123'> #沒有相符的傳回None print(pnum) pnum = ckrule.findall(locals()['msg%s'%i]) #search也可以改用findall,會找全部相符的 #回傳格式串列 ['0955-234-543', '0977-778-543'],沒有相符的傳回None #上面範例也可以改寫如下 import re word = r'\d{4}-\d{3}-\d{3}' #規則可以改寫成這樣的,相同的用{}填入數字 msg1 = "我的電話是0932-321-123" msg2 = "我有兩隻電話:0955-234-543,0977-778-543,你保留一下" for i in range(1,4): pnum = re.findall(word, locals()['msg%s'%i]) #減少compile,直接使用re #格式是re.findall(規則, 字串, Flags),Flags可以省略 #格式是re.search(規則, 字串, Flags),Flags可以省略 print(pnum) #搜尋結果轉成tuple import re word = r'(\(\d{2}\))(\d{8})' msg1 = "我的電話是(02)12345678" msg2 = "我有兩隻電話:(03)12345678,(03)87654321,你保留一下" for i in range(1,3): pnum = re.search(word, locals()['msg%s'%i]) pnumf, pnumb = pnum.groups() #pnum.groups()的格式是tuple #可以多項指定,也可以使用pnum.groups(0) 類推 print(pnumf,pnumb) #search可以搭配group()或group(n)取出相符的子字串,例如規則是'John(son|pon|agr)' word='john(son|per|iqe)(aa|bb)' msg = "I see johnsonaa ,johnperbb and johnppdcc go to out room" mtw = re.search(word, msg) print(mtw) print(mtw.group()) print(mtw.group(1)) #son print(mtw.group(2)) #aa #使用?查詢,範例import re word = r'(\(\d{2}\))?(\d{8})' msg1 = "我的電話是(02)12345678" msg2 = "我有兩隻電話:12345678,(03)87654321,你保留一下" for i in range(1,3): pnum = re.findall(word, locals()['msg%s'%i]) print(pnum) #使用?查詢 word = 'john((gg)*son)' msg = "I call johnggggggson" pnum = re.search(word, msg) print(pnum.group()) #搜尋忽略字母大小寫 word = 'john|TOM' msg = "John, tom and Mary" pnum = re.findall(word, msg, re.I) #Flag位置寫re.I 或是 re.IGNORECASE 皆可 print(pnum) #重複次數範例 (son){3} #搜尋'sonsonson',所以'sonsons'不符合 (son){2,4} #搜尋'sonson','sonsonson','sonsonsonson'皆符合 (son){2,} #son重複2次以上皆符合(含2次) (son){,10} #son重複10次以下皆符合(含10次) 範例 pattern = '(son){3,5}' #貪婪模式:python預設模式,以下範例執行會找出'sonsonsonsonson'(最多符合的) pattern = '(son){3,5}?' #非貪婪模式:以下範例執行會找出'sonsonson'(最少符合的) msg = 'sonsonsonsonson' txt = re.search(pattern, msg) print(txt.group()) MatchObject物件 re.match #和re.search功能相同,不同的是re.match搜尋字串最前面,找不到就回傳None #使用match和search搜尋成功時可用 txt = re.match(pattern, msg) txt.group() #傳回搜尋到字串 txt.end() #傳回搜尋到字串的結束位置 txt.start() #傳回搜尋到字串的起始位置 txt.span() #傳回搜尋到字串的(起始,結束)位置 result = re.sub(pattern, newstr, msg) #pattern取代規則 #newstr要更換的新內容 #msg搜尋的字串 #搜尋成功時,將結果字串傳給result,原msg不受影響 #搜尋到多筆相同字串時,這些字串全部被取代 #搜尋失敗,將msg內容傳給result 範例 import re pattern = r'CIA (\w)\w*' newstr = r'\1***' #\1表示第一組對映(\w)使用原字,剩下的\w*全用*** msg = 'CIA Mark , CIA Mary, CIA John' txt = re.sub(pattern, newstr, msg) print(txt) #印出 M*** , M***, J*** #Flag同時放許多參數 dstr = re.search(pattern, msg, re.VERBOSE|re.IGNORECASE|re.DOTALL) 比較複雜的正規是表達範例 #電話號碼處理 pattern = r'''( (\d{2}|\(\d{2}\))? #區域號碼,可省略 (\s|-)? #分隔符號(-或是空格),可省略 (\d{8}) #電話號碼 (\s*(ext|ext.)\s*\d{2,4})? #分機號碼2-4位數號碼 )''' #或者 pattern = r'(\d{2}|\(\d{2}\))?(\s|-)?(\d{8})(\s*(ext|ext.)\s*\d{2,4})?' #電子郵件搜尋 pattern = r'''( [a-zA-Z0-9_.]+ #帳號 @ # @ 符號 [a-zA-Z0-9_.]+ #domain \. # . 符號 [a-zA-Z]{2,4} #機構分類com edu等 ([\.])? # . 符號,可省略 ([a-zA-Z]{2,4})? #國碼,美國是省略的 )''' ``` ### 第27節 * sys系統模組 * https://docs.python.org/zh-tw/3/library/sys.html ```python= #可以控制python shell視窗訊息 import sys sys.version #python版本 sys.stdin.readline(n) #取得螢幕視窗輸入input的資料,和input()功能相同 #輸入的格式預設是字串 # n代表要讀取的字元數,不設定代表全讀,中文字或空白都算1個字元 #目前在python shell視窗可以,但在anaconda未嘗試成功 sys.stdout.write("ABC") #在螢幕上輸出字串,若是python shell還會列出輸出的字元數 sys.argv[0] #開啟cmd視窗執行第0個元素,一般是要執行檔案的位置與檔名 #如c:> python d:\pythonfile\out7.py 參數1 參數2 #d:\pythonfile\out7.py就是元素0,參數1是元素1,參數2是元素2(有空格就被視為另一個元素)..... ``` * math * https://docs.python.org/zh-tw/3/library/math.html ```python= math.isqrt(n) #整數平方根(開根號),n為要開根號的數 ``` ### 第28節 * Numpy * 支援多維度空間的陣列與矩陣運算 * https://numpy.org/doc/stable/index.html * https://simplelearn.tw/2022/09/01/hello-numpy%EF%BC%81%EF%BD%9Cnumpy-%E5%85%A5%E9%96%80%E8%A9%B3%E7%B4%B0%E4%BB%8B%E7%B4%B9-2022%E6%9B%B4%E6%96%B0%E7%89%88/ ```python import numpy as np np.array*([1.6, 2, 3.5, 4]) # 產生一維陣列 np.array([(2.5, 1, 3, 4.5), (5, 6, 7, 8)], dtype = float) # 產生二維陣列 np.zeros((2, 3)) #建立一個2x3,數值全是0陣列 #產生等距的陣列 np.arange(0,20,10) #arange(start, stop, step) #start起始值,預設是0,stop結束值(但所產生的陣列通常不包含此值),step陣列相鄰元素的間距,預設值是1 #start和step可以省略 #此可使用浮點數(小數),彌補range的不足 np.arange(0,15).reshape(5,3) #將產生的0-14等15個數字循序排列成5行3欄的陣列 #前面產生的數字量要和後面的陣列元素數量相同 np.random.seed() #搭配random.random......等亂數指令 #括弧內的數可以隨意設,只要是相同的數,取出來的亂數會相同 #不設此命令時或括弧內不放數字時,每次的亂數都不同 np.random.random(N) #產生N個0-1之間的隨機數,N不填為輸出一個數字 np.random.randn(N) #產生具有常態分配的隨機數,N可以是陣列(例如(5,3,4)三維陣列),N不填為輸出一個數字 np.random.rand(N) #產生介於0-1之間的數,可以是0,不會是1,N可以是陣列(例如(5,3,4)三維陣列),N不填為輸出一個數字 np.random.randint(low,high,size=6,dtype='l') #產生介於low到high中的整數,數量由size控制,low的數包含在可取得數內 #hight可以省略,省略時則為0-low之間的整數 #dtype為數據類型,可省略,預設為np.int numpy.random.normal(loc=0.0, scale=1.0, size=None) #標準常態分布隨機取數 #loc:float,可省略,預設為0,此概率分佈的平均值 #scale:float,可省略,預設為1,此概率分佈的標準差(對應於分佈的寬度,scale越大越矮胖,scale越小,越瘦高) #size:int or tuple of ints,可省略,預設為輸出一個值,但有設定時會輸出陣列(即使指定為1) numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0) #產生等距的陣列 #start:起始值。 #stop:最終值 #num:要生成的樣本數。默認值為50,可選參數,必須為非負數 #endpoint:如果是True,則停止是最後一個樣本。否則,不包括在內。默認值為True 可選參數 #retstep:如果為True,則返回(樣本,步長),其中step是樣本之間的間隔, 可選參數 #dtype:輸出數組的類型。如果dtype未給出,則從其他輸入參數推斷數據類型, 可選參數 #axis: 可選參數 np.sin(int) #產生數字的sin值 np.cos(int) #產生數字的cos值 np.abs(int) #產生絕對值 --- ``` ###### tags: `教學`