# 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/)
* 注意圖形的使用意義
* 
* 
* 範例
* 
``` 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
* 適用於多項唯一型資料的交叉比對
``` 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整理比較

```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點止
* 玩家未爆牌下,莊家爆牌算玩家贏,莊家未爆牌時,看點數,大的人贏
* 流程圖
* 作業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=
#作業:電子時鐘
#以類別的方式設計一個電子計時時鐘
#可以手動輸入起始的時分秒
```

```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: `教學`