---
# System prepended metadata

title: PYTHON 自學筆記

---

# PYTHON 自學筆記
# 第一周進度
# 基礎概念---第一章
**標頭檔**
**#!/usr/bin/python**
**#-*- coding: UTF-8 -*-**
**1.在賦予一變數值時，不須賦予其資料型態(如int、float、double)**
**2.在賦予新值之後，會把舊值覆蓋過去**
**3.尚未被定義的變數名稱不可作為運算用途**
示範如下
```python=
a=5
b=a+x(錯誤，無定義X值)
```
## 運算子
|  語法 |描述  | 賦值運算子  | 優先順序  | 
|---|---|---|---|
| a** | 開根號 | **=  | 1 | 
| a*b | 乘法 | *= | 2 | 
| a/b | 除法 | /= | 2 | 
| a//b | 整除| //= | 2 | 
| a%b | 取餘數 |%=　| 2 | 
| a+b |  加法|　+=| 3 | 
| a-b | 減法 |-=　| 3 |
## 基本輸入和輸出
**Python使用的輸入指令為input，若需要將input值轉換為數值，則可以加上資料型態來轉換**
示範如下
```python=
a=int(input('enter a  integer'))(此為輸入整數之範例)
b=float(input('enter a  integer'))(此為輸入整數之範例)
```
**Python的輸出方法為print**
示範如下
```python=
print('the length is',a)
```
## 函式def
在Python的開發環境中，可以將程式寫入函式當中，並在需要時呼叫執行，Python則是提供了def關鍵字來定義函式
使用方式為**def+關鍵字+括弧+冒號，即為def main():** 
**縮排對於分層非常重要**
## if 敘述句
使用方式為 **if+敘述句+冒號**
若要外加指令式，只有一個時加**else+冒號**，有多個指令式的話，中間的就加上**elif+冒號**，結尾那個用**else+冒號**。
## while敘述句
使用方式為 **while+敘述句+冒號**
此執行方法為若是符合此敘述句之條件，則跳入迴圈內重複進行直到其重新將值回傳到頂部重新測試不通過，才會跳過後結束。
也可以使用**break**來強制跳出整個迴圈，也可以用**continue**來強制跳出本次執行到下次執行迴圈
## PYTHON主要布林運算子
| 運算子 | 意義         |
| ------ | ------------ |
| and    | 兩值同時符合 |
| or     | 其中一值符合 |
| not    | 期望值的相反 |


## List、Tuple、For、Dictionary、set用法
**LIST**
不像是C或C++的list，Python 的list可以同時容納多種型態的資料在括號裡面

**TUPLE**
Tuple的概念與list雷同，但Tuple不支援List的更改方式，任何用此類修改方式的皆無效
""**
**FOR**
> For語法補充

| 語法                | 效果                                                                       |
| ------------------- | -------------------------------------------------------------------------- |
| range(end)          | 從0開始遞增，到end-1結束                                                   |
| range(beg,end)      | 從beg開始遞增，到end-1結束                                                 |
| range(beg,end,step) | 從beg開始遞增，以step值不斷增加直到end-1結束(可以設定為負數，便會向後計數) |

**DICTIONARY**
以一變數紀錄一堆值，其紀錄之區域以大括弧括起，其使用方式為 **{key1:value1,key2:value2}**
且在之後還可以替未含值的變數賦值，其使用方式為
**dictionary name['name']=value**
其主要在用dictionary查找需要的值時，試圖尋找不存在(尚未定義)的key時會導致程式錯誤，因此使用如下方法可以確保此key存在
**dictionary name.get(key或是[value])**

**SET**
其類似於dictionary的方式，但是括號中的值皆不會有重複的可能
其建立方法，修改方法為
```python=
my_set=set(value)(建立set)
my_set.add(value)(增加值)
my_set.remove(value)(刪除值)
```
**GLOBAL**
作為不管在程式的任何一個地方都可以做修改的數值

# 進階字串功能---第二章
## 字串基礎
基本上用法與C++相同
關於句子中的雙引號和單引號
**可以在單引號裡面的掛號加上雙引號，或是在雙引號裡面的掛號加上單引號(依照當下的狀況來更改，若要在句子間添加單引號，則可以用雙引號框外面)**
**可以使用連續三個雙引號來建立一個文字引號字串，這樣便可以直接在裡面隨意加上單引號和雙引號**
你也可以以代稱再加上
示範如下:
```python=
s1='Hello'
s2="""I'm ANDY HOU"""
s3=s1+' '+s2  #這樣便會連結兩個字串，中間還會有一個空格
print(s3)

my_str='a'
my_str+='b'
my_str+='c'
print(my_str) #輸出abc
```
## 數值轉換
**type(data_object,transform way)**
對於數值字串的轉換，使用的便會是**type(data_object,transform way)**
用法如下:
**STR**
其工作跟C++的stringstream有著剛好相反的特性，**str**的功能為將數字轉換回字，可以更方便我們去計算其位數或是數字出現之頻率。
```python=
int('10001',2)  #二進位碼10001以二進位方式解讀
float('1E',16)  #十六進位碼1E以十六進位方式解讀
----------------
S=str(2008)
print('the length is',len(s),'digits') 
```
## 字串處理
```python=
a_string = "bHkloY"
a_string.upper()      #全部字元轉成大寫
a_string.lower()      #全部字元轉成小寫，特別針對ASCII編碼，也就是‘A-Z’有效
a_string.casefold()   #對於其他語言（非漢語或英文）中把大寫轉換為小寫的情況只能用 casefold() 方法。
a_string.title()      #首字轉成大寫
a_string.capitalize   #每個字詞的首字轉成大寫
a_string.swapacase    #將大小寫顛倒
sorted(a_string)      #排序後輸出
```
## 字串切片處理
```python=
string[start:end] #設定切片start與end
string[:end]#從頭切到end
string[start:]#從start切到尾
string[:]#從頭切到尾
string[start:end:step] #設定切片start與end，並以跳躍step的方式來切出字元
```
## 字元函式
**ord() and chr()**
兩者正好為相反含意，**ord()** 代表將ASCII碼轉換為數值，**chr()** 是將數值轉會為ASCII碼
**separator_string.join(list)**
若想要在許多的字串中連接相同的東西，便可以加入欲分割之字元，再加入要分割的list便可分割
**strip**
``` python=
str.strip(extra_char='') #去除前方和後方字元
str.lstrip(extra_char='') #去除前方字元
str.rstrip(extra_char='') #去除後方字元
```
## 對齊方法
```python=
str.ljust(width[,fillchar]) #向左對齊
str.rjust(width[,fillchar]) #向右對齊
str.center(width[,fillchar]) #向左對齊
```
# 第二周進度
# 進階list功能---第三章
**1.在python的list中，盡量不要混合資料型態，在PYHTON3.0中，除了整數與浮點數可以混用以外，混合資料型態會導致無法使用 sort()** 
**2.list是可變的，因此可以直接修改單一值**
**3.尋找索引值必須是在此list的規定範圍內，因此超出list範圍的值會引發IndexError**
**基礎list函數**
## 複製list以及複製list內容
```python=
a_list=[1,2,3]
b_list=a_list #此為同步兩個相同的list，代表說只要修改其中一方，另一方的值也會得到更動
c_list=a_list[:]#複製全部的List值
```
## list切片
```python=
list[start:end] #設定切片start與end
list[:end]#從頭切到end
list[start:]#從start切到尾
list[:]#從頭切到尾
list[start:end:step] #設定切片start與end，並以跳躍step的方式來切出字元
```
## 賦值給切片
```python=
my_list=[10,20,30,40,50]
my_list[1:4]=[707,777] #把20,30,40替換成707,777
```
## 淺層複製以及深層複製
淺層複製的複製方式為前面全部進行逐元素複製，但是只要只要在list的值中在建立一個list，此時便無法複製，而轉為與要複製的list同步，說明了淺層複製只會複製到第一層的資料，第二層以後的資料便全部轉為公用形式，因此若是修改複製後的list，連原本的list也會被修改到，因此，必須要使用深度複製才能達到list全複製的效果。
```python=
#淺層複製方法
a_list=[1,2[5,10]]
b_list=[:]
#深層複製方法
import copy
a_list=[1,2[5,10]]
b_list=copy.deepcopy(a_list)
```
## list函式
```python=
len(collection) #回傳集合的長度(所有集合物件都適用)
max(collection) #回傳最大的集合值
min(collection) #回傳最小的集合值
reversed(collection) #反轉list
sorted(collection) #回傳排序完成的list
sum(collection) #只要list中的內含物都是數字，相加後回傳
```
```python=
my_list.append(1) #在my_list中加入1
my_list.extend([1,2,3])#一次加入多個值
my_list.remove(1) #在my_list中移除第一個搜尋到的1
my_list.clear()#全部清除
my_list.insert(index,value)#在index位置上放入值
enumerate(list_name,start=0)
my_list.index(search things)#在List中查找值
```
## list作為堆疊工具
## reduce
```python=
import functools #引進reduce使用工具functools
def add_func(a,b):
    return a+b
def mul_func(a,b):
    return a*b
n=5
a_list=list(range(1,n+1))
triangle_num=functools/reduce(add_func,a_list)
fact_num=functools/reduce(mul_func,a_list)
#把a_list裡面的值以兩個為一組帶入，算完後放回，並再次抓取兩個做運算，直到結束
```
## lambda
lanbda可以定義為只用一次的小函式，因此每個使用的lambda都需命名，才可以保留他所算出的值
```python=
my_f=lambda x,y:x+y #定義此lambda函式
print(my_f(3,7)) #輸出10
```
## list綜合表達式
```python=
#普通表達式
b_list[]
for i in a_list:
b_ist.append(i*i)
#綜合表達式
b_list[i*i#欲得到之結果  
for i in a_list]#欲執行之動作
    b_list[i*i for i in a_list]#綜合
#綜合表達式Dictionary
keys=['BOB','CAROL','TED','ALICE']
vals=[4.0,4.0,3.75,3.9]
grade_dict={key[i]:vals[i] for i in range len(keys)}
grade_dict={key:vals for key,vals in zip(keys,vals)}#加快寫法
```
**使用綜合表達式，list需用中括號，set用大括號
set的綜合表達式(value for statement    if condition)
dictionary的綜合表達式(key:value  for statement    if condition)**
# 捷徑、命令列與套件---第四章
**程式設計捷徑**
一.讓述句接續直到結束
**Way1**利用反斜線連接 
**Way2**放置文字於小、中、大括號內(閉合括號)
二.搭配使用for+enumerate功能
三.使用多重賦值
四.使用進階tuple賦值
```python=
a=1
b=0
c,d=3,4
e=3,4,5 #e為tuple
a,b=b,a #兩值交換

tup=1,2,3
a,b,c=tup
print(a,b,c)#輸出1,2,3

a,*b,c=[10,20,30,40,50]
a=[10]
*b=[20,30,40]
c=[50]
```
七.回傳多個值
**return對計算完的值的使用方式相當重要**
八.使用布林值和"not"
**述句if上除了可以以肯定句造句，也可以用if not condition來寫出否定句造句**
九.把字串視為字元組成的list
**於確認回文時相當有用，如以下程式碼**
```python=
#回文檢測示範
test_part=input("please insert the string!")
a_list=[test_part.upper() for i in test_part if test_part.isalnum()]
print(a_list[:]=a_list[::-1])
```
十.不要寫不必要的迴圈
**多利用內建函數來許寫程式，加快速度**
十一.使用函式表模擬"switch"
**將欲使用式子放入if elif迴圈中，再利用其值來呼叫當中的式子，達到有如C++中的switch case 的技巧，也能利用**
十二.正確使用"is"
十三.使用一行式"for"迴圈
**for 述句:欲執行動作**
十四.將多個述句壓縮到一行
**利用冒號和分號來撰寫多個述句再同一行當中**
十五.撰寫單行if/then/else
十六.使用互動式開發環境降低"print"對效能的影響
**使用能夠盡量讓print減少運行次數的撰寫方式來寫，能讓程式跑得比較快**
十七.在大數字中放入底線
**1000000跟1_000_000在電腦中所得到的結果相同，但是較容易閱讀
十八.星號加在print(*名稱) 上時，可以輸出未打包版本的list
```python=
li=[1,2,3]
print(*li)#輸出1,2,3
print(li)#輸出[1,2,3]
```
## PYTHON套件
```python=
import re
import math
import random
import decimal
import fractions
import array
import numpy
import numpy.random
import matplotlib.pyplot
import pandas
```
**import someting as 代稱，這個述句為簡化接下來每次引用的名稱，因此使用了簡化，便可以縮短程式碼，看起來更乾淨**
## *args and **kwargs
以***arg**來定義函式，可以訪問任意長度的輸入值的list
而以 ** **kwargs**來定義函式，可以訪問任意長度的輸入值的dictionary
```python=
def my_func(*args):#*args
    print('the number of args is %d',len(args))
    for item in args:
    print(items)

my_func(10,20,30,40)#輸入10,20,30,40
the number of args is 4#輸出值
10
20
30
40

def pr_vals_2(*args,**kwargs):#args and keargs
    for i in args:
    print(i)
    for k in kwargs:
    print(k,":",kwargs[k])

pr_vals_2(1,2,3,4,a=100,b=200)
1#輸出值 
2 
3
4
a:100
b:200
```
# 第三周進度
# 準確地格式化文字---第五章
## 使用百分比符號運算子進行格式化
其大致上的%格式皆與c++和c語言格式差不多
| 格式符號 |意義 |
|--|--|
|%d , %i | 整數|
|%F , %f | 浮點數 |
|%E , %e  | 指數型態浮點數(大E和小e)|
|%X , %x  | 十六進位整數 |
|%o|八進位整數|
|%s|字串形式|
|%G , %g| 浮點數，以最短規格的大E和小e表示|
|%%|一個百分比符號|
定義一句字串可以使用 **%-[字串寬度][.向左對齊格數][欲格式化之格式]**
若是無特別設定 **.向左對齊格數**的話，便會自動向右對齊，若無指定字串寬度，則會自己向左對齊，要是輸出格式為整數，用於對齊的0會放在左方，若是浮點數，則會放在右方。若要字串寬度為一可變數，則須將格式改為 **%*[欲格式化之格式]%(空格格數,欲輸出字串)**
## 全域format函式
**大括號可容納所有型態的資料**
```python=
print('{} plus {} equals {}'.format(25,75,100))#產生25 plus 75 equals 100

fss='{} said that he want {} slice of {}'
print(fss.format(david,2,pizza))#輸出david said that he want 2 slice of pizza
```
## 依照索引值決定使用順序
可在規定範圍內自由指定在format中的函數要以第幾位出現，但是絕對不行指定超過(format位數-1)的值
```python=
print("{}{}{}".format(10,20,30)#輸出10,20,30
print('{2} {1} {0}'.format(10,20,30))#輸出30,20,10
print('{3} {1} {0}'.format(10,20,30))#錯誤
print('{0},{0},{1},{1}'.format(100,200))#輸出100,100,200,200
------------
#類似陣列選取作法
a_list=[100,200,300]
b_list=[500,600,700]
print({0[1]:})#印出第一個引數中的第1+1個元素
```
## 'repr'與字串轉換
**當repr套用在字串上時，會產生出其在原始程式碼中表達的方式**
```python=
a='please remember to \n read the book'
print(a)#正常輸出
print('{}'.format(a))#正常輸出
print(repr(a))#輸出'please remember to \n read the book'
print('{!r}'.format(a))#輸出'please remember to \n read the book'
```
## 文字對齊:"填補"和"對齊"字元
**格式:[[fill] align width]**
```python=
print'{:->24}'.format('Hey billy G, pick me!')#輸出---Hey billy G, pick me!
print(format('TOM','*<6.10'))#輸出以*為填補符號、向左對齊、字串指定寬度為6，且超過10長度的字串都會被強行截斷
```
如上述示範所示，"-"代表的是填補於前方的字元，">"則代表要向右對齊"24"則是表示這行字串需要24格空位來擺放，**但若沒有對齊字元，則"-"便不會被視為是填補字元**
若要加上正負號，則需再format方加上，若加在輸出格式中，則只會輸出正數，因為"{:-}"只可以印出有負數的負號
# 正規表達式，第一部分---第六章
## 一個實際例子--電話號碼
```python=
import re #匯入正規表達式套件
pattern=r'\d\d\d-\d\d\d\d'#r為資料型別
s=input('enter tel. number: ')
if re.match(pattern,s):
    print('number accpeted')
else:
    print('incorrect number')
```
**re.match 和re.fullmatch之差別在於match只需搜尋到需要之格式的內容即可，後面若再增加字元或是數字也不會影響輸出結果，但若後方多新增字元，fullmatch則會一併算入，導致偵測結果錯誤。**
## 正規表達式的工作原理:編譯與執行
若要多次使用同一正規表達式，則可以使用 **object_name=re.compile(pattern)** 來建立一個可以重複使用的正規表達式，
範例如下
```python=
import re#匯入正規表達式套件
reg1=re.compile(r'ca*b$')#建立一個可以重複使用的表達式，樣式為'ca*b'
def test_item(s):
    if re.match(reg1,s):
        print(s,'is a match')
    else:
        print(s,'is not a match')
test_item('caaaaab')#測試實用性
test_item('caaxxdb')    
```
## 多選擇運算子|
**在使用多選擇運算子時，須注意小括號的使用以及搭配的文字順序，因為多選擇運算子具有的是最低的優先順序，因此括號會明顯影響執行結果，如下
若是使用ax|yz來排序，要成功執行此程式必須為ax或是yz
![](https://i.imgur.com/NXzTS6K.png)
而若是用a(x|z)y得到的結果則是如下，可以看見不論是用axy還是azy都可以成功執行
![](https://i.imgur.com/wazS6w4.png)
因此若是擴大到單字之組合也會有相同的概念，如cat|dog，若是輸入其一也可以成功執行**
## 函式旗標
| 旗標 |縮寫 | 描述 |
|--|--|--|
|ASCII |A | 使用ASCII |
|IGNORANCE| I | 匹配皆不區分大小寫 |
|DEBUG|  | 印出除錯資訊|
|LOCALE| L | 在匹配文數字元、單辭邊界和數字時，遵守LOCALE區域設定 |
|MULTILINE|M| 使特殊字元^和$匹配行開頭和結尾以及字串的開頭和結尾 |
|DOTALL|S| 點運算子(.)匹配所有字元，包括行尾 |
|UNICODE|U| 在匹配文數字元、單辭邊界和數字時，遵守UNICODE分類 |
|VERBOSE|X|除非空白屬於字元集合，否則樣式中的空白將會被忽略。這個旗標讓我們在程式碼中撰寫更漂亮的表達式  |
## 正規表達式:基本語法摘要
**描述字元:用於指定一個特定得字元或是字元之一，如"任何數字"或是"任何集合" 
字元集合:從指定的一組值中匹配一個字元
量詞:可允許重複無數次的字元被寫入表達式中
群組:用小括號以及大括號組成更大的群組**
### 描述字元

| 特殊字元 | 描述| 
| -------- | -------------------------------------------------- |
| . | 可以匹配任一字元|                                       
| ^ | 字串開頭的子字串或排除指定字元或群組，例如 'a[^b]c' 配對除了 'abc' 之外的任何 a 開頭 c 結尾的三字元組合。 |
| $ | 字串結尾的子字串，例如 'abc$' 配對以 'abc' 結尾的字串。|
| * | 單一字元或群組出現任意次數，例如 'ab*' 配對 'a' 、 'ab' 或 'abb' 等等。|
| + | 單一字元或群組出現至少一次，例如 'ab+' 配對 'ab' 或 'abb' 等等。|
| ? | 單一字元或群組 0 或 1 次，例如 'ab+' 配對 'a' 或 'ab'| 
| {m,n} | 單一字元或群組的 m 到 n 倍數，例如 'a{6}' 為連續六個 'a' ， 'a{3,6}' 為三到六個 'a'|
| [] | 對中括弧內的字元形成集合，例如 '[a-z]' 為所有英文小寫字母。|
|  | 單一字元或群組的或，例如 'a|b' 為 'a' 或 'b' |
| () | 對小括弧內的字元形成群組。|                  
| \A | 字串的開頭字元。|                 
| \b | 作為單字的界線字元，例如 r'\bfoo\b' 配對 'foo' 或 'bar foo baz' 。|
| \B | 作為字元的界線字元，例如 r'py\B' 配對 'python' 或 'py3' 。|
| \d | 數字，從 0 到 9 。|                                   
| \D | 非數字。|    
| \s | 各種空白符號，包括新行符號 \n 。|
| \S | 非空白符號。|
| \w | 任意文字字元，包括數字。|
| \W | 非文字字元，包括空白符號。|                               
| \Z | 字串的結尾字元。|
### 字元集合
[char_set] :匹配集合中的任一字元
[^char_set] :匹配不在集合中的任一字元
**在括號內的東西通常如字面上的意思去解釋，負號具有特殊意義(通常表示範圍)**

```python=
import re
re1=re.compile(r'c[aeiou]t')
if re.match(re1,"cat"):
    print("success!")
else:
    print("unsuccessful!")
cat
cet
cit
cot
cut
#以上範例皆會通過查驗
#綜合運用
import re
re1=re.compile(r'c[aeiou]+t')#融合兩種描述字元
if re.match(re1,"cqt"):
    print("success!")
else:
    print("unsuccessful!")
cattt
cot
cutttt
#以上範例皆會通過查驗
符號偵測
import re
re1='+'
if re.match(r'[+-*/%],re1)
print("Success")
```
### 樣式量詞
| 語法  | 描述                   |
| ----- | ---------------------- |
| expr* | 零次、一次至多個匹配項 |
| expr+ | 一次至多個匹配項       |
| expr? | 零次至一次的匹配項     |
| expr1/expr2      |  選擇匹配expr1或是expr2 |
| expr{n}   | 使其只限匹配N次|
| expr{m,n}| 使其匹配在m次以上，n次以下的字元|
| expr{m,}| 在m次以上的數值皆可匹配|
|expr{,n}|從0到n次以下|
| (expr)|    群組功能:作為匹配整個群組時的必要工具                    |
|  \n  | 所有輸入成功的群組內，找出順位第n個群組    |
```python=
import re 
re1=re.compile(r'\d\d\d-\d\d\d-\d\d\d\d')
re2=re.compile(r'\d{3}-\d{3}-\d{4}')
if re.match(re1,123-456-7890)
if re.match(re2,123-456-7890)#兩者結果相同
```
### 連續匹配
**若要執行如密碼確認等事，則需一個一個將條件列出，並且將條件一一列出，然後進行連續匹配
若一密碼設定規則如下**
> 每個字元必須是大寫或是小寫，數字，或是底線，或一個標點符號:@#$%^&*!
> 最低總長為8個字元
> 必須至少含有一個數字
> 必須包含一個可被接受的標點符號
因此實際執行便是
```python=
import re 
pat1=r'(\w|[@#$%^&*!]){8,}$' #$為字串結束符號，表示不可在後方加上任意空格以及符號
pat2=r'.*\d'
pat3=r'.*[a-zA-Z]'
pat4=r'.*[@#$%^&*!]'
def verify password (s):
b=(re.match(pat1,s) and re.match(pat2,s) and re.match(pat3,s) and re.match(pat4,s))
return bool(s)
```
### 使用MATCH物件
match物件除了用來作為回傳布林值的工具以外，還可以用來回傳群組內的東西
| 語法|描述| 
| -------- | -------- | 
| group(n) | 回傳指定的第n組字串 |
|group()|輸出全部已匹配字串|
|groupdict()|回傳一個由所以具名組所組成的dictionary，格式為name:text|
|lastindex|最後一個分組索引值|
範例如下
```python=
import re 
pat1=r'(a+)(b+)(c+)'
m=re.match(pat1,"abbcccee")
print(m.group(0))#輸出偵測到有關字串的部分
print(m.group(1))#輸出第一個字串有關(a+)的字串部分
print(m.group(2))#輸出第二個字串有關(b+)的字串部分
print(m.group(3))#輸出第三個字串有關(c+)的字串部分
輸出結果---------
abbccc
a
bb
ccc
```
### 迭代搜尋"findall"
re.findall類似於貪婪搜尋法，列出需要匹配之物件，然後針對欲搜尋之字串進行貪婪搜尋法
**list=re.findall(pattern,target_string,flags=0)**
若是表達式出現判讀錯誤，則建議要加上一個小括號再將其放入findall式子中
### 使用實例-搜尋重複樣式
若是在打字時遇到的連續打了同一個字兩次，則可用此程式校正
想法如下
the the為兩個字連續，因此若想要找出此樣式，則需記錄第一次的the，並且在空一格後，再次匹配the是否有連續重複
```python=
import re
s="the cow jumped over the the moon"
pat1=re.serach(r'(\w+) \1')
print(m.group(),'...found at',m.span())
```
# 正規表達式，第二部分---第七章
## 進階RexEx語法摘要
|(?:expr)|非標記分組，將expr視為單個單元，但不要標記執行時匹配的字元，目的是匹配字元，而不是要做分組標記|
|expr??|非貪婪版本的?運算子|
|expr*?|使用非貪婪匹配領或多個expr實例|
|expr+?|使用非貪婪匹配領或多個expr實例，提供另一個匹配目標字串的方法，匹配盡可能少的字串|
# 類別和魔術方法---第八章
# Decimal、money與其他類別---第九章
## 浮點數的限制
浮點數雖能準確的存取一個數字，但每當浮點數運算在處理一個算式時，都會出現一個很小的捨入誤差，但是若要這種錯誤不被發生，最好的辦法便是使用**Decimal** 
## Decimal介紹
```python=
from decimal import Decimal #新增Decimal函數
my_dec=Decimal()#將要運算的值放入Decimal中以防止出現計算誤差
print(my_dec)#印出定義的精確數值
```
在使用Decimal函數時，雖然可以確保在Decimal()定義的數值不會跑掉，但是若是一開始定義的數值類別不對，那儲存到的也會不是正確的數值
```python=
from decimal import Decimal 
d=Decimal(0.1)#使用浮點數定義
print(d+d+d)
>>> 0.3000000000000000166533453694
------------------------------------
e=Decimal('0.1')#以字串定義
print(e+e+e)
>>> 0.3
```
因此以字串定義可以防止系統誤判，代表著"我想用這個字串中的數值來作為計算"
### round & normalize
但decimal在進行乘法時，若有兩數相乘，精度會自動增加，因此，若要控制其經度，其方法便是用**round**來控制
```python=
from decimal import Decimal 
d=Decimal('0.020')
e=Decimal('0.030')
print(d*e)
>>> 0.000600
print(round(d*e,4))
>>> 0.0006
```
而**normalize**功能則是將精度削減至最低需求，若是小數點後的數字皆為0，那則有可能直接化簡為整數
```python=
from decimal import Decimal 
d=Decimal('0.020')
d2=d.normalize()
print(d)
print(d2)
>>> 0.020#未經標準化的數值
>>> 0.02#標準化後
e=Decimal('2.00')
e=e.normalize()
print(e)
>>> 2
```
**實作---金錢認證**
```python=
from decimal import Decimal
total=Decimal('0.00')
while True:
    s=input('input amount un dollars and cents(#.##):')
    if not s :
        break 
    d=Decimal(s)
    d=round(d,2)
    total += d
print('the money total is :',total)
```
## Money




# Numpy套件
| NUMPY函式    | 產出                                                  |
| ------------ | ----------------------------------------------------- |
| arange       | 將指定語法內的整數統整成array，與PYTHON range函式類似 |
| linspace     | 在指定的範圍內以間隔生成array，具有處理福點數值的能力 |
| ones         | 產生初始值均為1的array(整數、浮點數或布林true值)      |
| eyes         | 對角線上有1的array，其他儲存個都是0                   |
| zeros        | 產生初始值均為0的array(整數、浮點數或布林false值)     |
| full         | 每個位置都放置指定數值的array                         |
| copy         | 將另一array數值逐一複製                               |
```python=
# 引入 numpy 模組
import numpy as np
np1 = np.array([1, 2, 3])
np2 = np.array([3, 4, 5])
# 陣列相加
print(np1 + np2) # [4 6 8]
# 顯示相關資訊
print(np1.ndim, np1.shape, np1.dtype) # 1 (3,) int64 => 一維陣列, 三個元素, 資料型別
 
a=np.arange(1,1_000_001)
print(sum(a))
>>> 500,000,500,000
```


