---
# System prepended metadata

title: Python 學習筆記

---

# Python 學習筆記

# 變量 (variable)

變量存儲在內存中的值。 這就意味著在創建變量時會在內存中開闢一個空間。
基於變量的數據類型，解釋器會分配指定內存，並決定什麼數據可以被存儲在內存中。
因此，變量可以指定不同的數據類型，這些變量可以存儲整數，小數或字符。

> 變量名 = 值

## 命名規則

1.由數字、字母或底線組成
2.不能數字開頭
3.不能使用Python內建關鍵字　(ex：if、for、while、print、input...)
4.大小寫嚴格區分　(ex：a跟A為不同的變數名稱)

## 命名習慣
1.見名知義，好閱讀好懂
2.大駝峰　(ex：MyName)
3.小駝峰　(ex：myName)
4.底線　(ex：my_name)

## 變量賦值
```python==
my_name = 'Joecy'
print(my_name)   # Joecy
```

## 多個變量賦值
創建一個對象，值為1，三個變量被分配到相同的內存空間上。
```python==
a = b = c = 1
print(a) # 1
print(b) # 1
print(c) # 1
```

# 數據與符號

![](https://i.imgur.com/TAQ2i9y.png)


## 格式化數據

1.準備數據
2.格式化符號輸出數據

 > %d -- 有符號的十進制整數
 %s -- 字串
 %f -- 浮點數
 f'{表達式}' -- 較簡潔的語法, 主流用法

<font color="#FF8040">**範例**</font>

age = 35
name = 'Joecy'
weight = 52.56
stu_id = 1
stu_id2 = 93154213
employee_id = 791016

- 今年我的年齡是X歲 -- 有符號的十進制整數 %d
```python=
print('今年我的年齡是%d歲' % age) #今年我的年齡是35歲
```

- 我的名字是x -- 字串 %s
```python=
print('我的名字是%s' % name) #我的名字是Joecy
```


- 我的體重是x公斤 -- 浮點數 %f , %f中間插入.x,表示小數點後要保留x位小數
```python=
print('我的體重是%.2f公斤' % weight) #我的體重是52.56公斤
```


- 我的學號是x
```python=
print('我的學號是%d' % stu_id) # 我的學號是1
```


- 我的學號是001 -- %0xd , 表示輸出的整數是x位數 , 不足以0補齊 , 超出以當前位數原樣輸出
```python=
print('我的學號是%03d' % stu_id) # 我的學號是001
```
```python=
print('我的名字是%s' % name) # 我的學號是93154213
```


- 我的名字是x , 今年x歲了
```python=
print('我的名字是%s, 今年%d歲了' % (name, age)) # 我的名字是Joecy, 今年35歲了
```


- 我的名字是x , 明年x歲了
```python=
print('我的名字是%s, 明年%d歲了' % (name, age + 1)) # 我的名字是Joecy, 明年36歲了
```

- 我的名字是x , 今年x歲了 , 體重x公斤 , 員編是x
```python=
print('我的名字是%s, 今年%d歲了, 體重%.2f公斤, 員編是%08d' % (name, age, weight, employee_id))
```

- 我的名字是x , 今年x歲了 , 體重x公斤 , 員編是x -- 因為印出來都是string , 可以全部用%s取代
```python=
print('我的名字是%s, 今年%s歲了, 體重%s公斤, 員編是%s' % (name, age, weight, employee_id)) # 我的名字是Joecy, 今年35歲了, 體重52.56公斤, 員編是791016
```

- 語法 f'{表達式}' -- 輸出內容同上 , 但語法比較簡潔、較常用
```python=
print(f'我的名字是{name}, 今年{age}歲了, 體重{weight}公斤, 員編是{employee_id}')  # 我的名字是Joecy, 今年35歲了, 體重52.56公斤, 員編是791016
```

## 轉義符號(換行)

1.\n -- 表示換行
2.\t -- 表示按四個空白鍵的縮進=Tab
3.end='' -- 表示末尾不換行

- \n
```python=
print('Hello,\nworld,\nbeatiful') 
# Hello,
# world,
# beatiful
```

- \t
```python=
print('Hello,\tworld,\tbeatiful') 
# Hello,	world,	beatiful
```

- end=''
```python=
print('Hello,', end='')
print('world,', end='')
print('beatiful')
# Hello,world,beatiful
```

## input

### 介紹

1.書寫 input
  input('提示訊息')
  
2.特點
 2.1 遇到input, 等待用戶輸入
 2.2 接收input存成變量 f'{}'
 2.3 input接收到用戶任意輸入的數據, 都當作字串處理

```python=
password = input('請輸入您的密碼: ') # 請輸入您的密碼:
print(f'您輸入的密碼是{password}') # 您輸入的密碼是
print(type(password))  # # 印出來輸出的類型是string <class 'str'>
```

### 轉換input接收到的數據類型

1.input
2.檢測input數據類型為str
3.轉換數據類型

*   int(x) -- 將x轉換為整數
*   float(x) -- 將x轉換為浮點數
*   str(x) -- 將x轉換為字符串
*   eval(str) -- 用來計算在字符串中的有效Python表達式，並返回一個對象
*   tuple(s) -- 將序列s轉換為一個元組
*   list(s) -- 將序列s轉換為一個列表
  
4.檢測是否轉換成功

<font color="#FF8040">**範例**</font>

- ins() -- 將數據轉換成整數型
```python=
num = input('請輸入數字：')
print(type(num))  # str, <class 'str'>
print(int(num))   # 6
print(type(int(num)))  # int, <class 'int'>
```

- float() -- 將數據轉換成浮點數型
num = 1
str1 = '10'
```python=
print(float(num)) # 1.0
print(type(float(num)))  # <class 'float'>

print(float(str1))  # 10.0
print(type(float(str1)))  # <class 'float'>
```

- tuple(s) -- 將序列轉換為一個元組
list1 = [10, 20, 30]
```python=
print(tuple(list1))  # (10, 20, 30)
print(type(tuple(list1)))  # <class 'tuple'>
```



## 算數運算符

加　　　+  
減　　　-  
乘　　　*  
除　　　/  
整除　　// 
取餘數　%  
次方　　** 
運算優先 () 

tips：()優於 ** 優於 * / // % 優於 + - 

```python=
print(40 / (7 - 3) * 2) # 20.0
print(9 % 4)　# 1
```

## 複合賦值運算符
(先執行算數運算符，再將結果賦值給左邊的變量)

>加法賦值運算符 +=　->　c+=a 等於 c=c+a
減法賦值運算符 -=　->　c-=a 等於 c=c-a
乘法賦值運算符 *=　->　c*=a 等於 c=c*a
除法賦值運算符 /=　->　c/=a 等於 c=c/
整除賦值運算符 //=　->　c//=a 等於 c=c//a
取餘賦值運算符 %=　->　c%=a 等於 c=c%a
冪賦值運算符 2顆星=　->　c**=a 等於 c=c**a


<font color="#FF8040">**範例**</font>


- 加法賦值運算符 
```python=
a = 10
a += 1
print(a)　# 11
```

```python=
b = 10
b += 1 + 2
print(b) 　# 13
```


- 減法賦值運算符 
```python=
c = 10
c -= 1
print(c)　# 9
```


- 乘法賦值運算符
```python=
d = 10
d *= 1 + 2
print(d)　# 30，先算1+2, 再乘法賦值變成 10*3=30
```



## 比較運算符

>==　判斷相等，如果兩個操作數的結果相等,則條件結果為真(True),否則為假(False)
   ex：a = 3, b = 3 則 a == b為True
   

>!=　不等於，如果兩個操作數的結果不相等,則條件結果為真(True),否則為假(False)
   ex：a = 1, b = 3 則 a != b為True, a == b為False

>＞　左邊運算符操作結果是否大於右側的操作結果,若大於,則條件真(True),否則為假(False)
   ex：a = 3, b = 2 則 a > b為True

>＜　左邊運算符操作結果是否小於右側的操作結果,若小於,則條件真(True),否則為假(False)
   ex：a = 3, b = 2 則 a < b為False

>＞=　左邊運算符操作結果是否大於等於右側的操作結果,若大於等於,則條件真(True),否則為假(False)
   ex：a = 3, b = 3 則 a >= b為True

>＜=　左邊運算符操作結果是否小於等於右側的操作結果,若小於等於,則條件真(True),否則為假(False)
   ex：a = 3, b = 3 則 a <= b為True


<font color="#FF8040">**範例**</font>

```python=
print(12 == 5) 　# False
print(12 != 5) 　# True
print(12 >= 5) 　# True
print(6.7 >= 6.7) 　# True
print("There" != "There") 　# False
print("There" >= "Them") 　# True，因字元在字母表越後面，表示該字元的數值越大,r在字母表排在m之後, 因此回傳True
```


## 邏輯運算符

>and　xx"與"xx，前後都真才為真,只要有一個是假,前後表達式都是假
or　　xx"或"xx，前後任一表達式成立則為真,若都假才假
not　非，表達式為True,則返回False;若表達式為False,則返回True

<font color="#FF8040">**範例**</font>
a = 0
b = 1
c = 2

- and(與), 都真才真
```python=
print((a < b) and (b < c))  # True
print((a > b) and (b < c))  # True
print((a < b) and (b > c))  # False
```

- and運算符, 只要一個值為0,則結果為0,否則以會後一個非0數字為結果
```python=
print(a and b)  # 0
print(b and a)  # 0
print(b and c)  # 2
print(c and b)  # 1
```

- or(或)：一真則真,都假才假
```python=
print((a < b) or (b < c))  # True
print((a > b) or (b < c))  # True
print((a > b) or (b > c))  # False
```

- or運算符, 只有在所有值為0,結果才為0,否則以會第一個非0數字為結果
```python=
print(a or b)  #1
print(b or a)  #1
print(b or c)  #1
print(c or b)  #2
```

- not(非)：取反
```python=
print(not (c > b ))  # False
print(not (c < b ))  # True
```

# 字串

## 表達方式



 - 單引號
```python=
a = 'Joecy'
print(a)  # Joecy
print(type(a))  # <class 'str'>
```



- 雙引號
```python=
b = "Joecy"
print(b)  # Joecy
print(type(b))  # <class 'str'>
```


- 三引號 支援enter換行
```python=
c = '''I'm
Joecy'''
print(c)
print(type(c))
```


## 下標 (索引)

數據在程式運作過程中，會儲存在內存
這些字符數據從0開始順序分配一個編號 --使用這個編號精準找到某個字符數據 -- 使用下標(索引)

<font color="#FF8040">**範例**</font>

```python=
str1 = 'abcdefg'
print(str1[0])  # a
print(str1[1])  # b
print(str1[6])  # g
```

## 切片 (slice)

對於擷取串列中某部分的內容，在python中稱之為切片
切片的用法是需要指定使用的第一個元素和最後一個元素的索引足標
Python中符合序列的有序序列都支援切片,例如列表,字串,元組
https://www.itread01.com/p/433323.html



>格式:【start：end：step】
>start:起始索引,從0開始,-1表示結束
 end:結束索引
 step:步長,end-start,步長為正時,從左向右取值。步長為負時,反向取值
     

<font color="#FF8040">**範例**</font>
```python=
str1 = '012345678'
print(str1[2:5])   # 234
print(str1[2:7:2])  # 246
print(str1[:5])   # 01234 -- 起始索引沒寫，默認從0開始選取
print(str1[2:])   # 2345678 -- 結束索引沒寫，表示選取到最後
print(str1[:])   # 012345678 -- 起始索引和結束索引都沒寫，表示選取所有
```

- 負數
```python=
print(str1[::-1])   # 876543210 -- 如果步長為負值，表示倒序選取
print(str1[-4:-1])   # 567  索引-1表示最後1個數據，依次向前類推  所以-1是指8 -4是指1
```

- 其他
```python=
print(str1[-4:-1:1])   # 567
print(str1[-4:-1:-1])   # 選不出數據，因為-4開始到-1結束，選取方向為從左到右，但步長-1表示從右向左選取，衝突了
print(str1[-1:-4:-1])   # 876  起始到終點的方向和步長的方向一致，可以選出
print(str1[8:5:-1])   # 876
```

## 查找

可以查找子串在字串中的位置或出現次數

>find() : 檢查某個子串是否在字串，存在則返回該子串開始的位置下標；不存在則回-1
index() : 檢查某個子串是否在字串，存在則返回該子串開始的位置下標；不存在則報錯
count() : 返回某個子串在字串中出現的次數
rfind() : 同find()功能，但查找方向由右邊開始
rindex() : 同index()功能，但查找方向由右邊開始
len() : 查長度

<font color="#FF8040">**範例**</font>

- 字串序列.find(子串, 開始位置下標, 結束位置下標) 沒寫開始和結束下標，則會在整個字串中找

```python=
print(mystr.find('and'))  # 12
print(mystr.find('and', 15, 30))  # 23
print(mystr.find('ands'))  # -1，表示不存在，找不到ands
```

- 字串序列.index(子串, 開始位置下標, 結束位置下標) 沒寫開始和結束下標，則會在整個字串中找

```python=
print(mystr.index('and'))  # 12
print(mystr.index('and', 15, 30))  # 23
print(mystr.index('ands'))  # 找不到ands,直接報錯 substring not found
```

- 字串序列.count(子串, 開始位置下標, 結束位置下標)

```python=
print(mystr.count('and', 15, 30))  # 1次
print(mystr.count('and'))  # 3次
print(mystr.count('ands'))  # 0次，表示不存在
```

- 字串序列.rfind(子串, 開始位置下標, 結束位置下標)

```python=
print(mystr.rfind('and'))  # 35
print(mystr.rfind('and', 15, 30))  # 23
print(mystr.rfind('ands'))  # -1，表示不存在，找不到ands
print(len(mystr))  # 查字串長度 total 45
```

- 字串序列.rindex(子串, 開始位置下標, 結束位置下標)

```python=
print(mystr.rindex('and'))  # 35
print(mystr.rindex('and', 15, 30))  # 23
print(mystr.rindex('ands'))  # 找不到ands,直接報錯 substring not found
```

## 修改字串

替換、分割、合併 

>replace() : 替換
split() : 分割 -- 返回一個列表，丟失分割字符
joint() : 合併 -- 用字符或子串將多個字串合併成為一個新的字串


## 迴圈
while
for


<font color="#FF8040">**範例**</font>

```python=
name_list = ['Tom', 'Lily', 'Rose']
print(len(name_list)) # 3

i = 0
```

- while
```python=
while i < len(name_list):
    print(name_list[i]) 
    i += 1
    
# Tom
# Lily
# Rose
```

- for
```python=
for i in name_list:
    print(i)
    
# Tom
# Lily
# Rose
```


## 巢狀列表

一個列表裡包含了其他子列表

<font color="#FF8040">**範例**</font>

```python=
name_list = [['Tom', 'Lily', 'Rose'], ['小明', '小紅', '小王'], ['張三', '李四', '老王']]
print(name_list)
```
- 下標查找數據 ,先找到所在的列表, 再找到數據
```python=
print(name_list[0][1])  # 找到Lily
```


## 綜合練習

將8位老師隨機分配到3個辦公室

>1.準備數據:
-> 8位老師 -- 列表
-> 3個辦公室 -- 巢狀列表<br>
2.隨機分配到辦公室
  把老師的名字寫入辦公室列表<br>
3.驗證是否分配成功


```python=
import random
```

- 1.準備數據
```python=
teachers = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I']
offices = [[], [], []]
```
- 2.分配老師到辦公室 -- 取每個老師放到辦公室列表，追加老師列表數據
```python=
for name in teachers:
    # 列表追加數據 : append(選這個),extend, insert
    # 隨機到offices列表，列表有3個子列表，import random 個數
    num = random.randint(0, 2)
    # print(num)
    offices[num].append(name)
```

- 3.驗證是否分配成功
```python=
for office in offices:
    print(f'辦公室人數是{len(office)},老師分別是：')
    for name in office:
        print(name)
```

# 迴圈

讓代碼更高效的重複執行
分成 while 和 for 兩種

## while迴圈

> while 條件：
    條件成立重複執行的代碼一
    條件成立重複執行的代碼二
    ......

https://www.runoob.com/python3/python3-loop.html


<font color="#FF8040">**範例**</font>
1. 重複執行5次 print('對不起我錯了！')

>tips:
計數 起始值=1 , 終點值=5
設計變量依據計數累加的計數器

```python=
i = 1
while i <= 5:
    print('對不起我錯了！')
    i += 1

print('好啦原諒你') 

"""
對不起我錯了！
對不起我錯了！
對不起我錯了！
對不起我錯了！
對不起我錯了！
好啦原諒你
"""
```

2. 1～100的數字累加　－－　1+2+3+4+...+100= 結果

>tips:
1.準備作加法運算的數據, 1-100 增量為1
2.準備變量保存將來運算的結果
3.迴圈做加法運算
4.打印結果
5.驗證結果正確性，將範圍縮小計算

```python=
# 準備數據
i = 1

# 結果變量
result = 0

# 迴圈計算結果
while i <= 100:
    # 加法運算 前兩個數相加結果 再加第三個數 --> 每一次相加則更新result變量值
    result += i
    i += 1

print(f'1 到 100 的累加總共是{result}') # 1 到 100 的累加總共是5050
```

### 跳出迴圈 (循環)

1.break : 當某些條件成立，完全退出迴圈
2.continue : 退出當前迴圈，繼續執行下一次迴圈的代碼

- break
ex:吃5個蘋果，吃到第3個飽了不吃第4.5個

```python=
i = 1
while i <=5:
    if i == 4:
        print('吃了3個飽了，不吃了')
        break
    print(f'吃了第{i}個蘋果了')
    i += 1
    
"""
吃了第1個蘋果了
吃了第2個蘋果了
吃了第3個蘋果了
吃了3個飽了，不吃了
"""
```

- continue
ex:吃5個蘋果，吃到第3個有蟲不吃，繼續吃第4個第5個

```python=
i = 1
while i <=5:
    if i == 3:
        print('吃到有蟲的，這個不吃了')
        # 如果使用continue，在continue之前一定要修改計數器，否則會進入無窮迴圈(因為不會執行continue後面的代碼)
        i += 1
        continue
    print(f'吃了第{i}個蘋果了')
    i += 1
    
"""
吃了第1個蘋果了
吃了第2個蘋果了
吃到有蟲的，這個不吃了
吃了第4個蘋果了
吃了第5個蘋果了
"""
```

### 巢狀迴圈


>while 條件1:
　　條件1成立執行的代碼
 　　...
　　while 條件2:
　　　　條件2成立執行的代碼
　　　　...




## for迴圈

for 自定義的變數 in 序列(Sequence)
迴圈會依序從序列 (例如: 一連串清單資料，一組數字或一個名單)裡取得元素
並將元素指派給前面自訂的變數，然後執行迴圈裡的內容
https://medium.com/ccclub/ccclub-python-for-beginners-tutorial-4990a5757aa6

在Python 中，序列类型包括
字串str：''or""
列表list：[]
元组tuple：()
字典Dictionary：{}
集合：{}或者 set()

<font color="#FF8040">**範例**</font>

1.準備一個數據序列
2.for

```python=
sequences = [0, 1, 2, 3, 4, 5]
for i in sequences:
    print(i) 

"""
0
1
2
3
4
5
"""
```

### 跳出迴圈 (循環)

1.break : 當某些條件成立，完全退出迴圈
2.continue : 退出當前迴圈，繼續執行下一次迴圈的代碼

<font color="#FF8040">**範例**</font>

- break

```python=
str = 'Museum12345'

for i in str:
    if i == 'm':
        print('遇到m退出迴圈')
        break
    print(i)

"""
M
u
s
e
u
遇到m退出迴圈
"""
```

- continue

```python=
for i in str:
    if i == 'm':
        print('遇到m退出當前一次迴圈')
        continue
    print(i)

"""
M
u
s
e
u
遇到m退出當前一次迴圈
1
2
3
4
5
"""
```

### 搭配else

1.while和For都可以配合else使用
2.當迴圈正常結束後，才會執行else下方的代碼
3.break跳出迴圈，不會執行else下方的代碼
4.continue退出當前迴圈但有正常執行完迴圈，會執行else下方的代碼


>For 臨時變量 in 序列:
　　重複執行的代碼
 　　...
else:
　　迴圈正常結束之後要執行的代碼
    

<font color="#FF8040">**範例**</font>

```python=
Str2 = 'itheima'
for i in Str2:
    print(i)
else:
    print('迴圈正常結束之後要執行的代碼')

"""
i
t
h
e
i
m
a
迴圈正常結束之後要執行的代碼
"""
```

- break：不會執行else下方的代碼
```python=
Str1 = 'itheima'
for i in Str1:
    if i == 'e':
        break
        # continue
    print(i)
else:
    print('遇到e pass')

"""
i
t
h
"""
```

- continue：因為continue是退出當前一次迴圈，繼續下一次迴圈，所以該迴圈在continue下還是可以正常結束，當迴圈結束後，則會執行else下方的代碼

```python=
Str1 = 'itheima'

for i in Str1:
    if i == 'e':
        # break
        continue
    print(i)
else:
    print('遇到e pass')

"""
i
t
h
i
m
a
遇到e pass
"""
```

### 總結

1. for迴圈是在序列窮盡時停止(有明顯的頭跟尾)，while迴圈是在條件不成立時停止
2. for迴圈語句申明循環變量，while迴圈語句判斷迴圈條件
3. 需要在讀文本文件中有很多邏輯判斷時，採用while比較好 ; 沒有復雜的邏輯判斷時用for比較好。

### range()

>range(start, stop, step) 函式。裡面有一些參數可以設定:
>
>start: 計數從start 開始。預設是從0 開始。例如range（5）等價於range（0， 5）;
>
>stop: 計數到stop 結束，但**不包括stop**。例如：range（0， 5） 是[0, 1, 2, 3, 4]沒有5
>
>step：步長，預設為1。例如：range（0， 5） 等價於range(0, 5, 1)

```python=
r=range(1, 5)
print(type(r)) 

# <class 'range'>
```

如果想將 range() 值放在串列裡呈現可以使用一個 tuple 或 list 將 range 物件實例
```python=
a = list(range(1, 5))
print(a) 

# [1, 2, 3, 4]
```

內建 range() 函式使用時機大多數在迴圈上會看見
```python=
for i in range(3):
    print(i)
"""
0
1
2
"""
```


# if 條件式
### if

條件語句 if
條件成立才執行某些代碼，條件不成立則不執行這些代碼

>if條件：
　　條件成立執行的代碼一
　　條件成立執行的代碼二
　　......


```python==
age = int(input('請輸入您的年齡：'))
# input接收到用戶輸入的數據是字串，須轉成跟條件一樣都是整數才能做判斷

if age >= 18:
    print(f'你的年齡是{age},已經成年可以上網')
```


### if 搭配 else

條件語句 if else
條件成立執行if下方的代碼, 條件不成立則執行else下方的代碼

>if 條件：
　　條件成立執行的代碼一
　　條件成立執行的代碼二
    ......
else:
　　條件不成立執行的代碼一
　　條件不成立執行的代碼二
　　......

```python==
age = int(input('請輸入您的年齡：'))
# input接收到用戶輸入的數據是字串，須轉成跟條件一樣都是整數才能做判斷

if age >= 18:
    print(f'你的年齡是{age},已經成年可以上網')
    
else:
    print(f'你輸入的年齡是{age},趕快回家吧！')
```


### if 、elif 、else 

多重判斷
條件成立執行if下方的代碼, 條件不成立則執行else下方的代碼
備註：只要if下方的條件成立，就只會執行到該代碼

>if 條件1：
　　條件1成立執行的代碼一
　　條件1成立執行的代碼二
    ......
elif 條件2:
　　條件2成立執行的代碼一
　　條件2成立執行的代碼二
    ......
else:
　　以上條件都不成立執行的代碼


<font color="#FF8040">**範例**</font>
未滿18歲不得工作，超過65歲後退休


```python==
age = int(input('請輸入您的年齡：'))

if age < 18:
    print(f'你輸入的年齡是{age},還是童工喔！')

elif 18 <= age <= 65:
    print(f'你輸入的年齡是{age},合法勞工')

elif age > 65:
    print(f'你輸入的年齡是{age},可以退休囉！')
```


### if嵌套

>if 條件1：
　　條件1成立執行的代碼
　　條件1成立執行的代碼二
　　
　　if條件2：
　　　　條件2成立執行的代碼一
　　　　條件2成立執行的代碼二


<font color="#FF8040">**範例**</font>
坐公車，有錢才能上車，沒錢不能上車; 上車後，有位子才能坐，沒位子要站著

1. 判斷的依據：錢、空位
2. 判斷是否有錢：上車、不能上車
3. 上車後，是否能坐下：有空位、沒空位

```python==
money = {money}
seat = {seat}

if money >= 1:
    print('有錢可以上車啦')
    if seat >= 1:
        print('有空位可以坐下')
    else:
        print('但沒有空位，要站著了')
else:
    print('下次要帶錢才能上車喔')
```


### 隨機random

隨機取整數 

1.import random
2.random.函數名(開始,結束)
函數名=randint


```python==
import random
num = random.randint(0, 2)
print(num)
```


### if練習題 (玩家和電腦猜拳，判斷輸贏)



# 函式 (function)
### 介紹

函式就是把常用的程式碼包裝在一個區塊中，方便我們在寫程式時隨時呼叫、使用。
往後在遇到類似運算時，同樣的邏輯可以重複利用，而不需要再多寫好幾行的程式碼，
也讓我們在寫程式的過程中不容易出錯。

函式的使用分為2個階段，一定要先定義函式後，我們後面才能呼叫（使用）函式：

1. 定義
> def 函式名稱(函式參數):
    函式內部的程式碼

2. 呼叫
函式名稱(函式參數)

函式名稱自己定義 好閱讀 不可數字開頭或python的內部名稱
參數依需求可有可無

參考
https://alvis.tw/blog/python-function/
https://medium.com/ccclub/ccclub-python-for-beginners-tutorial-244862d98c18

### 注意事項

1. 函式一定要先定義再呼叫，否則會報錯
2. 如果沒有呼叫函式，則不會執行函式裡面的程式碼
3. 當呼叫函式時，IDE會先到定義函式的地方去執行下方的程式碼，當這些程式碼執行完
   再回到呼叫函式的地方繼續向下執行程式

<font color="#FF8040">**範例**</font>
一個函式，印出hello world

1. 先定義函式 (沒呼叫時不會執行)

```python==
def info_print():
    print('hello world')
```


2. 呼叫函式
```python==
info_print()    # hello world
```


### 參數

讓函式變的更靈活，傳入對應的任何指定數據
>實參：函式呼叫時，傳入的真實數據
形參：函式定義時，等待接收數據的參數

<font color="#FF8040">**範例**</font>
一個函式，固定加總數字1和2

* 方式1 : 直接定義一個加總等於3的function，再呼叫
```python==
def add_num1():
    results = 1 + 2
    print(results)
```
```python==
add_num1()
```

* 方式2 : 建立可以傳入2個參數加總的function，呼叫函式時傳入了真實的數據
```python==
def add_num2(a, b):
    results_2 = a + b
    print(results_2)
```
```python==
add_num2(10, 20)   # 30
add_num2(100, 200) # 300
```

### 返回值

如果需要可以返回結果給用戶，需要使用函數返回值

return作用
1.負責函式返回值
2.退出當前函式：return下方的所有程式碼（函式內部的程式碼）不再執行

<font color="#FF8040">**範例**</font>
製作一個計算器，計算任意兩個數字，並保存結果


1. 先定義函式 
```python=
def sum_num1(a, b):
    return a + b
```

2. 創建變量並呼叫 
```python==
results_3 = sum_num1(2, 33)
```
```python=
print(results_3)   # 35
```

### 返回值作為參數

```python=
def test3():
    return 50
```
```python=
def test4(num):
    print(num)
```
```python=
# 保存函式test3的返回值
a = test3()
# 將test3函式返回值所在的變數50,作為參數傳到test4函式
test4(a)  # 50
```

### 參數種類
1.位置參數 (location parameter)：調用函式時根據函數定義的參數位置來傳遞參數 (順序和個數必須要一致)

2.關鍵字參數 (keyword)：呼叫函式時，通過指定”傳遞參數名=傳遞參數值 key=value”傳入，清除了順序須一致的規則
呼叫函式時若有位置參數，位置參數只能出現在關鍵字參數之前，不管是在行參還是實參中

3.默認參數 (Default Parameter Values)：為參數提供默認值，呼叫函式時可以不傳入該默認參數的值，有傳入則修改默認參數值

4.可變參數：定義函數時，有時候我們不確定調用的時候會多少個參數,就可以使用可變參數

<font color="#0000C6">*args　非鍵值可變參數 - 傳進的所有參數都會被args變量收集，合併並返回一個元組()
**kwargs　鍵值可變參數 - 傳進的所有參數都會被kwargs變量收集，合併並返回一個字典{}</font>
args和kwargs 只是變量名，你可以寫vars和*vars實現相同的結果

<font color="#FF0000">注意：參數優先序，位置參數  > 默認參數　>　非鍵值可變參數　>　鍵值可變參數</font>


<font color="#FF8040">**範例**</font>


```python=
def user_info(name, age, gender):
    print(f'您的名字是{name}, 年齡{age}, 性別{gender}')
```

- 位置參數

```python==
user_info('Joecy', 35, 'girl')  # 您的名字是Joecy, 年齡35, 性別girl
```

- 關鍵字參數

```python==
user_info('batty', gender='girl', age=27)  
# batty是位置參數
# gender和age是關鍵字參數，以key=value傳入，不管順序
# 您的名字是batty, 年齡27, 性別girl
```

<font color="#FF0000">報錯！！</font>
```python==
user_info(gender='girl', age=27, 'batty')
# batty是位置參數
# 報錯，因位置參數順序與function不一致
```

- 默認參數

```python==
def user_info(name, age, gender='girl'):
    print(f'您的名字是{name}, 年齡{age}, 性別{gender}')
```
```python==
user_info('Joecy', 35)  # 您的名字是Joecy, 年齡35, 性別girl
```

```python==
user_info('Kevin', 39, 'boy')  # 您的名字是Kevin, 年齡39, 性別boy
```

- 可變參數 *args

```python==
def user_info(*args):
    print(args)

    
user_info('Tom', 20)  # ('Tom',20)
```

- 可變參數 **kwargs

```python==
def user_info(**kwargs):
    print(kwargs)


user_info(name='Tom', age=20)  
# {'name': 'Tom', 'age': 20}
```

### 遞迴函式


遞迴 (Recursion)
1.函式內部自己呼叫自己，只是解決問題的一種方式，不一定非要用
2.跟迴圈類似：基本可以互相替代
3.必須要有出口，要不會報錯(Previous line repeated 996 more times)，超出遞迴次數
4.迴圈編寫起來比較容易，閱讀起來比較難。遞迴編寫起來比較難，但是閱讀容易




> 需求：3以內的數字累加和 
3 + 2 + 1 = 3 + 2以內的數字累加 = 6
2以內的數字累加和 = 2 + 1以內的數字累加和
1以內的數字累加和 = 1 ---> 出口

```python=
def sum_numbers(num):
    # 2.設定出口
    if num == 1:
        return 1  # 如果是1，直接返回1
    # 1.當前數字 + 當前數字的累加和
    return num + sum_numbers(num-1)  # 如果不是，重複執行累加並返回結果


sum_result = sum_numbers(3)
print(sum_result)  # 6

```

![](https://i.imgur.com/SZ2Qjhv.png)

# 列表 (lsit)

一次性存儲多個不同類型的數據，並可以改動數據

## 查找

1.下標 用[]
2.函數

>index() 檢查某個數據是否在列表，存在則返回該數據開始的位置下標；不存在則報錯
count() 返回某個數據在列表中出現的次數，不存在則回0
len() 列表中數據的個數 p.s 公共操作


<font color="#FF8040">**範例**</font>

```python=
name_list = ['Tom', 'Lily', 'Rose']
```

- 下標
```python=
print(name_list[0])  # Tom
print(name_list[1])  # Lily
print(name_list[2])  # Rose
```

- 列表序列.index(數據, 開始位置下標, 結束位置下標)   p.s. find()不適用列表
```python=
print(name_list.index('Lily'))  # 1
print(name_list.index('Joecy')) # 直接報錯 ValueError: 'Joecy' is not in list
```


- 列表序列.count(數據, 開始位置下標, 結束位置下標)
```python=
print(name_list.count('Lily'))  # 1
print(name_list.count('Joecy'))  # 0
```

- len(列表序列)
```python=
print(len(name_list))  # 3
```

## 判斷指定數據是否存在

>in 判斷指定數據是否存在列表，是回True、否為False   p.s 公共操作
not in 判斷指定數據是否不存在列表，是回True、否為False    p.s 公共操作

<font color="#FF8040">**範例**</font>

```python=
name_list = ['Tom', 'Lily', 'Rose']
```

- in
```python=
print('Tom' in name_list)  # True
print('Joecy' in name_list)  # False
```

- not in
```python=
print('Tom' not in name_list)  # False
print('Joecy' not in name_list)  # True
```

- Testcase 查找用戶輸入的名字是否存在清單內
```python=
name = input('請輸入您的名字：')
if name in name_list:
    print(f'您輸入的名字是{name}，已在清單內')
else:
    print(f'您輸入的名字是{name}，不在清單內')
```


## 增加
>append() : 列表結尾贈加數據，若追加的是一個序列則追加整個序列到結尾
extend() : 列表表結尾贈加數據，若追加的是一個序列則將這個數列的數據逐一追加到結尾
insert() : 指定位置新增數據

**<font color="#FF00FF">!!!列表數據可以改動，為可變數據類型</font>**

<font color="#FF8040">**範例**</font>

```python=
name_list = ['Tom', 'Lily', 'Rose']
```

- 列表序列.append(數據)
```python=
name_list.append('Jack')
print(name_list) # ['Tom', 'Lily', 'Rose', 'Jack']
```

- 列表序列.append(數據) 
數據可以是元素也能是串列，它會把串列當成一個元素放進去
```python=
list = [1,2,3,4,5,6]
list.append(10)
list.append([11,12])  
print(list) # 串列直接放 [1, 2, 3, 4, 5, 6, 10, [11, 12]]
```

- 列表序列.extend(數據)
```python=
name_list.extend('Joe')  
print(name_list) # ['Tom', 'Lily', 'Rose', 'Jack', 'J', 'o', 'e']
name_list.extend(['Joe', 'Leo'])  
print(name_list) # ['Tom', 'Lily', 'Rose', 'Jack', 'J', 'o', 'e', 'Joe', 'Leo']
```

- 列表序列.insert(位置下標, 數據)
```python=
name_list2 = ['Tom', 'Lily', 'Rose']
name_list2.insert(1, 'Joecy')
print(name_list2) # ['Tom', 'Joecy', 'Lily', 'Rose']
```


## 刪除
>del() : 刪除列表，也可以刪除指定下標得數據
pop() : 刪除指定下標的數據(若沒有指定則默認最後一個)，並返回該數據
remove() : 移除列表中某個數據(符合的第一個)
clear() : 清空列表，印出來是顯示[]


- del 列表序列
```python=
name_list = ['Tom', 'Lily', 'Rose']
del name_list
print(name_list)  # NameError: name 'name_list' is not defined
```

```python=
name_list2 = ['Kevin', 'Joecy', 'Jack']
del name_list2[0]
print(name_list2)  # ['Joecy', 'Jack']
```


- 列表序列.pop(位置下標) 
```python=
name_list = ['Tom', 'Lily', 'Rose']
name_list.pop()
print(name_list)   # ['Tom', 'Lily'] 若沒有指定則默認最後一個

name_list.pop(1)
print(name_list)  # ['Tom']
```


- 列表序列.remove(數據)
```python=
name_list = ['Tom', 'Lily', 'Rose','Tom']
name_list.remove('Tom')
print(name_list)  # ['Lily', 'Rose', 'Tom']
```


- 列表序列.clear()
```python=
name_list = ['Tom', 'Lily', 'Rose']
name_list.clear()
print(name_list)  # []
```


## 修改
>列表序列[] 修改指定下標
reverse() : 逆序列表
sort() : 排序/升序 or 降序

<font color="#FF8040">**範例**</font>

```python=
name_list = ['Tom', 'Lily', 'Rose']
print(name_list)  # ['Joecy', 'Lily', 'Rose']
```

- 修改指定下標
```python=
name_list[0] = 'Joecy'
print(name_list)  # ['Joecy', 'Lily', 'Rose']
```

- 列表序列.reverse()
```python=
name_list.reverse()
print(name_list) # ['Rose', 'Lily', 'Joecy']
```

- 列表序列.sort(reverse=True or False)
reverse表示排序規則， True為降序、False為升序，沒寫reverse默認升序
```python=
list1 = [1, 5, 7, 3, 6, 8]
list1.sort(reverse=True)
print(list1)  # [8, 7, 6, 5, 3, 1]
```


## 複製
>copy()：將原數據保留，複製一份並存到另個一變量

<font color="#FF8040">**範例**</font>

```python=
new_list = ['Tom', 'Lily', 'Rose']
new_list2 = new_list.copy()
print(new_list2) # ['Tom', 'Lily', 'Rose']
```

## 列表生成式
作用：
用１個表達式創建１個有規律的列表，或控制１個有規律的列表
     是一種一邊迴圈一邊計算的機制
     把生成的元素放到前面，後面跟for迴圈並搭配range()，就可以把list建立出來
>寫法
[xx for xx in range()]

<font color="#FF8040">**範例
需求：建立1個0-10的列表**
</font>

先準備1個空的列表
```python=
list1 = []
list2 = []
list3 = []
```

- 方式1 : 用while迴圈，一次次追加數字到空的列表
```python=
i = 0
while i < 11:
    list1.append(i)
    i += 1

print(list1)  # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
```

- 方式2 : 用for迴圈
```python=
for i in range(11):
    list2.append(i)

print(list2)  # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
```

- 方式3 : 用列表生成式
```python=
list3 = [i for i in range(11)]
print(list3)  # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
```


# 字典 (dic)

每一個元素都由鍵 (key) 和值 (value) 構成，結構為key: value 。不同的元素之間會以逗號分隔，並且以大括號 {}圍住

## 查找
>1.key：若當前的key存在則返回對應的value，不存在則報錯
>2.函式
>* get()：當前的key存在則返回對應的value; 若當前的key不存在，則返回默認值，如果沒有默認值則返回none
>* keys()：查找字典序列中所有key對應的value們
>* values()：查找字典序列中所有value對應的key們
>* items()：查找字典序列中所有key和value，數據類型為元組


<font color="#FF8040">**範例**
</font>
```python=
dict1 = {'name': 'Kevin', 'age': 30, 'gender': 'boy'}
```

- key值查找
```python=
print(dict1['name'])  # Kevin
```
```python=
print(dict1['name'])  # 報錯 KeyError: 'id'
```

- 字典序列.get(key, 默認值)
```python=
print(dict1.get('name'))   # Kevin
print(dict1.get('id', 110))  # dict1中沒有key=id，只返回110
```
```python=
print(dict1.get('id'))  # key不存在，則返回none
```

- 字典序列.keys()
```python=
print(dict1.keys())   # dict_keys(['name', 'age', 'gender'])
```

- 字典序列.items()
```python=
print(dict1.items())  
# dict_items([('name', 'Kevin'), ('age', 30), ('gender', 'boy')])
```


## 新增(=修改)

>字典序列[key] = value
如果key存在，則直接修改key對應的值; 如果key不存在，則直接新增此健值對

<font color="#FF8040">**範例**
</font>
```python=
dict2 = {'name': 'Tom', 'age': 20, 'gender': 'boy'}
```

```python=
dict2['name'] = 'Joecy'
dict2['id'] = 111
```
```python=
print(dict2)  
# {'name': 'Joecy', 'age': 20, 'gender': 'boy', 'id': 111}
```





## 刪除
>del() : 刪除字典或字典中指定的鍵值,不存在的話會報錯
clear() : 清空字典, 最後保留一個空字典 {}

<font color="#FF8040">**範例**
</font>
```python=
dict3 = {'name': 'Joecy', 'age': 35, 'gender': 'girl'}
```

- del()
```python=
del dict3['age']
print(dict3)  # {'name': 'Joecy', 'gender': 'girl'}
```

- 字典序列.clear()
```python=
dict2.clear()
print(dict2)    # {}
```

## 創建新的字典
用fromkeys()，創建一個新字典，以序列 seq 中元素做字典的鍵，value 為字典所有key對應的初始值。
>寫法
dict.fromkeys(seq, val)
>* seq -- 這是將用於字典的key準備的值的列表。
>* value -- 如果提供的話則值將被設置為這個值，未設定則預設為None



<font color="#FF8040">**範例1**
</font>
```python=
combined_record_keys = ('pointType', 'txDate', 'txPoint', 'actionType', 'txNote', 'payAmount', 'itemQty')
```
- 序列.fromkeys()
```python=

expected_record_schema = dict.fromkeys(combined_record_keys)
print(expected_record_schema)
# {'pointType': None, 'txDate': None, 'txPoint': None, 'actionType': None, 'txNote': None, 'payAmount': None, 'itemQty': None}
```

<font color="#FF8040">**範例2**
</font>
```python=
seq = ('name', 'age', 'sex')
```
- 序列.fromkeys(seq, val)
```python=
dict = dict.fromkeys(seq, 10)
print(dict)
# {'name': 10, 'age': 10, 'sex': 10}
```


## 循環遍歷
>1.遍歷字典的key
2.遍歷字典的value
3.遍歷字典的元素(key:value)，數據類型為元組
4.遍歷字典的鍵值對

<font color="#FF8040">**範例**
</font>
```python=
dict4 = {'name': 'Patty', 'age': 40, 'gender': 'girl'}
```

- 遍歷字典的key
```python=
for key in dict4.keys():
    print(key)  # 返回序列中所有的key：name age gender
```

- 遍歷字典的value
```python=
for value in dict4.values():
    print(value)  # 返回序列中所有的value：Patty 40 girl
```

- 遍歷字典的元素(key:value)
```python=
for item in dict4.items():
    print(item)  
# 返回序列中所有的key:value，數據類型為元組，有2個數據，數據1是字典的key,數據2為字典的value
# ('name', 'Patty')
# ('age', 40)
# ('gender', 'girl')
```

- 遍歷字典的鍵值對
```python=
for key, value in dict4.items():
    print(f'{key} = {value}')  
# name = Patty 
# age = 40 
# gender = girl
```

## 字典生成式
作用：快速合併列表為字典(搭配len()) 或提取字典中目標數據(搭配items())
>ex：
list1 = ['name', 'age', 'gender']
list2 = ['Joecy', '36', 'woman']
>
>寫法
{key: value for key, value in ....}

* 需求1：建立1個字典,key是1-5的數字, value是這個數字的平方
```python=
dict1 = {i: i**2 for i in range(1, 6)}
print(dict1)  # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
```
* 需求2：將兩個列表合併為1個字典
如果兩個列表數據個數相同，用len統計任何一個列表個數
如果兩個列表數據個數不同，用len統計數據少的列表(統計數據多的會報錯)
```python=
dict2 = {list1[i]:list2[i] for i in range(len(list1))}
print(dict2) 

# {'name': 'Joecy', 'age': '36', 'gender': 'woman'}
```

* 需求3：提取字典中目標數據
 
```python=
counts = {'MBP': 268, 'HP': 125, 'DELL': 201, 'Lenovo': 199, 'acer': 99}

alist = counts.items()
print(type(alist)) 
# <class 'dict_items'>
```
items() 函式將字典元素轉換為 <class 'dict_items'>，其結果儲存在 alist 變數中。alist 需要被轉換為一個列表，因此須用 list() 函式將其型別化，然後將結果儲存在同一個變數中，即 alist。
https://www.delftstack.com/zh-tw/howto/python/python-convert-dictionary-to-list/

```python=
alist = list(alist)
print(alist)
# [('MBP', 268), ('HP', 125), ('DELL', 201), ('Lenovo', 199), ('acer', 99)]

print(alist[0])
# ('MBP', 268)
```
濾出上電腦數量>=200的字典數據
```python=
count1 = {key: value for key, value in counts.items() if value >= 200}
print(count1)  

# {'MBP': 268, 'DELL': 201}
```


# 類別 (class)

## 介紹

簡單來說，為物件(Object)的藍圖(blueprint)。
就像要生產一部汽車時，都會有設計圖，藉此可以知道此類汽車會有哪些特性及功能，

類別(Class)就類似設計圖，會定義未來產生物件(Object)時所擁有的屬性(Attribute)及方法(Method)。而定義類別的語法：

> class 類名():
    代碼
    ......

類名的命名原則習慣上使用Pascal命名法(大駝峰)，
也就是每個單字字首大寫，不得使用空白或底線分隔單字
https://www.learncodewithmike.com/2020/01/python-class.html

<font color="#FF8040">**範例
需求：洗衣機，功能：清洗衣服**
</font>


1. 定義洗衣機這個類別

```python==
class Washer():
    def wash(self):
        print('能洗衣服')
```


2. 創建物件

物件名 = 類名() -> 類的實例化
```python==
TOSHIBA = Washer()
```


3. 驗證成果

- 打印，結果會是內存位置

```python==
print(TOSHIBA)   # 結果會是內存位置 <__main__.Washer object at 0x000001C204FC57C0>
```

- 使用wash這個function：物件名.wash() -> 呼叫類的方法

```python==
TOSHIBA.wash()   # 能洗衣服
```


## self

指的是將來調用類別下該函數的物件
print(物件) = print(self) 的內存地址會是一樣



1. 定義洗衣機這個類別

```python==
class Washer2():
    def wash(self):
        print('我會洗衣服')
        print(self)
```


2. 創建物件

物件名 = 類名() -> 類的實例化
```python==
TOSHIBA2 = Washer2()
```


3. 驗證成果

- 打印，結果會是內存位置

```python==
print(TOSHIBA2)   # 結果會是內存位置 <__main__.Washer2 object at 0x00000131B6B3EFD0>
```

- 使用wash這個function：物件名.wash() -> 呼叫類的方法

```python==
TOSHIBA2.wash()  
# 我會洗衣服 、 <__main__.Washer2 object at 0x00000131B6B3EFD0>
```

 ## 多個物件
 
 一個類可以創建多個物件
多個物件在調用函數時，內存地址都不同

1. 定義類別

```python==
class Washer3():
    def wash(self):
        print('我會洗衣服啦啦啦')
        print(self)
```

2. 創建多個物件，調用到同個方法

```python==
TOSHIBA3 = Washer3()
TOSHIBA3.wash() 
# 我會洗衣服啦啦啦 、 <__main__.Washer3 object at 0x000001EBC969FFD0>
```

```python==
TOSHIBA4 = Washer3()
TOSHIBA4.wash()   
# 我會洗衣服啦啦啦 、 <__main__.Washer3 object at 0x000001EBC969FFA0>
```



 ## 屬性
 
即特徵，比如洗衣機的寬度、高度、重量...
可以幫不同的物件添加屬性

***類的外面添加 or 獲取物件屬性***
> 物件名.屬性名 = 值
 
<font color="#FF8040">**範例**
</font>

1. 定義類別

```python==
class Washer4():
    def wash(self):
        print('我會洗衣服啦啦啦')
```

2. 為物件添加屬性

```python==
LG.width = 500
LG.height = 800
```


3. 獲取物件的屬性

```python==
print(f'LG洗衣機的寬度是{LG.width}')
print(f'LG洗衣機的高度是{LG.height}')
```


***類的裡面添加 or 獲取物件屬性***
> self.屬性名

<font color="#FF8040">**範例**
</font>

1. 定義類別

```python==
class Washer5():
    def washer_info(self):
        print(f'國際牌洗衣機的寬度{self.width}')
        print(f'國際牌洗衣機的高度{self.height}')
```

2. 創建物件

物件名 = 類名() -> 類的實例化
```python==
Panasonic = Washer5()
```

3. 為物件添加屬性

```python==
Panasonic.width = 700
Panasonic.height = 900
```

4. 獲取物件的屬性

```python==
Panasonic.washer_info()
# 國際牌洗衣機的寬度700
# 國際牌洗衣機的高度900
```

## 魔法方法

魔法方法（Magic methods）
魔法方法是一種以雙下劃線開頭和結尾的一種特殊方法，
在使用類的時候非常常見，例如，經常會用到的__init__。
它的功能是作爲構造函數，能夠在類初始化時調用，
可以在初始化方法中定義一些初始化變量、初始化操作，
當執行到類內部時，會先執行這些方法。

>__init_(): 初始化
__str_(): 輸出物件資訊
__del_(): 刪除物件時調用



### __init__

__init__()方法，在創建一個物件時默認被調用，不需要手動調用
__init__(self)中的self參數，當前物件引用時python解釋器會自動傳遞

<font color="#FF8040">**範例**
</font>

1. 定義類別

```python==
class Washer6():
    # 定義__init__，添加實例屬性
    def __init__(self):
        self.width = 500
        self.height = 500

    def washer_info(self):
        print(f'國際牌洗衣機的寬度是{self.width},高度是{self.height}')
```


2. 創建物件

物件名 = 類名() -> 類的實例化
```python==
Panasonic = Washer6()
```

3. 呼叫類的方法

```python==
Panasonic.washer_info()
# 國際牌洗衣機的寬度是500,高度是500
```

### __init__(帶參數)

一個類可以創建多個對象
如何對不同的對象設置不同的初始化屬性

<font color="#FF8040">**範例**
</font>

1. 定義類別

```python==
class Washer7():
    # 定義__init__，添加實例屬性
    def __init__(self, width, height):
        self.width = width
        self.height = height

    def washer_info(self):
        print(f'洗衣機的寬度是{self.width},高度是{self.height}')
```


2. 創建多個物件，帶入不同的參數

物件1
```python==
LG = Washer7(110, 150)
```

物件2
```python==
TECO = Washer7(150, 180)
```


3. 呼叫類的方法

```python==
LG.washer_info()
# 洗衣機的寬度是110,高度是150
```
```python==
TECO.washer_info()
# 洗衣機的寬度是150,高度是180
```


### __str__

回傳一個代表這個對象的字串 (一定要是字串)
<font color="#FF8040">**範例**
</font>

1. 定義類別

```python==
class Washer8():
    # 定義__init__，添加實例屬性
    def __init__(self, width, height):
        self.width = width
        self.height = height

    def __str__(self):
        return '這是toshiba的說明書'
```


2. 創建物件

物件名 = 類名() -> 類的實例化
```python==
toshiba = Washer8(110, 150)
```

3. 呼叫類的方法

```python==
print(toshiba)  # 這是toshiba的說明書
```


### __del__

建立物件後，Python直譯器預設呼叫__init__()方法。
當刪除一個物件時，Python直譯器也會預設呼叫一個方法，這個方法為__del__()方法。
在Python中，對於開發者來說很少會直接銷燬物件(如果需要，應該使用del關鍵字銷燬)。
Python的記憶體管理機制能夠很好的勝任這份工作。
也就是說,不管是手動呼叫del還是由Python自動回收都會觸發__del__方法執行。

<font color="#FF8040">**範例**
</font>

1. 定義類別

```python==
class Washer9():
    # 定義__init__，添加實例屬性
    def __init__(self):
        self.width = 300

    def __del__(self):
        print(f'{self}對象已經刪除')
```


2. 創建物件

物件名 = 類名() -> 類的實例化
```python==
toshiba = Washer9()
 # <__main__.Washer7 object at 0x0000018C099DFFD0>對象已經刪除
```



## 小結

1.創建 類 (Class)
class 類名():
    代碼

2.物件 (Object)
物件 = 類名()

3.物件屬性 (Attribute)
* 類外面
物件名.屬性名 = 值
* 類裡面
self.屬性名 = 值

4.獲取物件屬性
* 類外面
物件名.屬性名
* 類裡面
self.屬性名

5.魔法方法
>__init__(): 初始化
__str__(): 輸出物件資訊
__del__(): 刪除物件時調用


## 綜合應用1 烤地瓜
依地瓜烤的時間，自動判斷熟度以及可以添加任意調味料

1. 定義類別：初始化屬性、被烤和添加調味料的方法、並輸出物件資訊（用__str__()）

```python==
class SweetPotato:
    def __init__(self):
        self.cook_time = 0
        self.cook_static = '生的'
        self.condimemts = []  # 用戶可能一次想要添加多種調味料，所以用list存取

    def cook(self, time):
        """烤地瓜的方法"""
        # 1.先計算地瓜烤過的時間
        # 2.再用整體時間(""累加"")判斷地瓜的狀態
        self.cook_time += time
        if 0 <= self.cook_time < 3:
            self.cook_static = '生的'
        elif 3 <= self.cook_time < 5:
            self.cook_static = '半生不熟'
        elif 5 <= self.cook_time < 8:
            self.cook_static = '熟了'
        elif self.cook_time >= 8:
            self.cook_static = '烤糊了'

    def add_condiments(self, condiment):
        """用戶要添加的調味料追加到調料列表"""
        self.condimemts.append(condiment)

    def __str__(self):
        return f'這個地瓜烤了{self.cook_time}分鐘，狀態是{self.cook_static},添加的調味料有{self.condimemts}'
```


2. 創建物件

物件名 = 類名() -> 類的實例化
```python==
digua1 = SweetPotato()
print(digua1)   # 初始狀態：這個地瓜烤了0分鐘，狀態是生的,添加的調味料有[]
```

3. 調用類的方法，並傳入參數：時間和調味調

```python==
digua1.cook(4)  
digua1.add_condiments('甘梅')
print(digua1)   # 這個地瓜烤了4分鐘，狀態是半生不熟,添加的調味料有['甘梅']
```

```python==
digua1.cook(2)  
digua1.add_condiments('胡椒')
print(digua1)   # 這個地瓜烤了6分鐘，狀態是熟了,添加的調味料有['甘梅', '胡椒']
```

```python==
digua1.cook(2)  
print(digua1)   # 這個地瓜烤了8分鐘，狀態是烤糊了,添加的調味料有['甘梅', '胡椒']
```

# 繼承 (Inheritance)

顧名思義，就是會有父類別(或稱基底類別Base Class)及子類別(Sub Class)的階層關係。
子類別會擁有父類別公開的屬性(Attribute)及方法(Method)。

所以Python繼承(Inheritance)的概念
就是將各類別(Class)會共同使用的屬性(Attribute)或方法(Method)放在一個獨立的類別(Class)中，
其它的類別(Class)透過繼承(Inheritance)的方式來擁有，降低程式碼的重複性。
https://www.learncodewithmike.com/2020/01/python-inheritance.html


<font color="#FF8040">**範例**</font>

1. 先定義父類A

```python==
class A():
    def __init__(self):
        self.num = 1

    def info_print(self):
        print(self.num)
```


2. 定義子類 繼承父類

```python==
class B(A):
    pass
```

3. 創建物件 調用方法驗證是否繼承成功

```python==
result = B()
result.info_print()  # 1
```

## 單繼承

子類繼承了父類，只有一個父類

1. 先定義父類A

```python==
class Master():
    def __init__(self):
        self.konfu = '古法配方'

    def info_print(self):
        print(f'運用{self.konfu}製作煎餅')
```


2. 定義子類 繼承父類

```python==
class Prentice(Master):
    pass
```

3. 創建物件 調用方法驗證是否繼承成功

```python==
classic_bread = Prentice()
print(classic_bread.konfu)  # 古法配方
classic_bread.info_print()  # 運用古法配方製作煎餅
```


## 多重繼承


多重繼承 (multiple inheritance) 
指子類別 (subclass) 可以同時繼承 (inheritance) 多個父類別 (superclass) ，好獲得不同父類別的特性。
當一個類繼曾多個父類時，優先繼承第一位父類的同名屬性和方法

>子類(父類1, 父類2):

<font color="#FF8040">**範例**</font>


1. 先定義父類A

```python==
class Master():
    def __init__(self):
        self.konfu = '古法配方'

    def info_print(self):
        print(f'運用{self.konfu}製作煎餅')
```

2. 創建另一個父類B

```python==
class Master2():
    def __init__(self):
        self.konfu = '黑糖配方'

    def new_print(self):
        print(f'運用{self.konfu}製作煎餅')
```

3. 定義子類 繼承2個父類

```python==
class Prentice(Master2, Master):
    pass
```

4. 創建物件 調用方法驗證是否繼承成功

```python==
new_bread = Prentice()
print(new_bread.konfu)  # 黑糖配方 (因為Master2在第一位)
new_bread.info_print()  # 運用黑糖配方製作煎餅
```


## 多重繼承 2

指子類別 (subclass) 可以同時繼承 (inheritance) 多個父類別 (superclass) ，好獲得不同父類別的特性。
子類若有和父類一樣的同名屬性和方法：子類創建物件和屬性時，默認使用子類的同名屬性和方法
https://openhome.cc/zh-tw/python/inheritance/mixin/


快速得到繼承順序
>print(子類.__mro__)

<font color="#FF8040">**範例**</font>


1. 先定義父類A

```python==
class Master():
    def __init__(self):
        self.konfu = '古法配方'

    def make_cake(self):
        print(f'運用{self.konfu}製作煎餅')
```

2. 創建另一個父類B

```python==
class Master2():
    def __init__(self):
        self.konfu = '黑糖配方'

    def make_cake(self):
        print(f'運用{self.konfu}製作煎餅')
```

3. 定義子類 繼承2個父類

```python==
class Prentice(Master2, Master):
    def __init__(self):
        self.konfu = '獨創配方'

    def make_cake(self):
        print(f'運用{self.konfu}製作煎餅')
```

4. 創建物件 調用屬性與方法

```python==
new_bread = Prentice()
new_bread.make_cake()  # 運用獨創配方製作煎餅（子類的）
print(Prentice.__mro__)
# (<class '__main__.Prentice'>, <class '__main__.Master2'>, <class '__main__.Master'>, <class 'object'>)
```

# PR學習

## enumerate()函式

Python enumerate()函式可以讓我們在迭代一個可迭代物件時，同時取得索引值和元素值。它可以讓我們在迭代時，不用另外寫一個計數器來記錄索引值，更加方便快捷

> enumerate(iterable, start=0)

iterable是一個可迭代物件，start是可選參數，用來指定索引值的起始值，預設為0。

<font color="#FF8040">**範例**</font>


* 使用方法
將可迭代物件傳入函式中，就可以得到一個enumerate物件，它是一個可迭代物件，每次迭代都會返回一個元組，元組的第一個元素是索引值，第二個元素是元素值。

1. 將一個列表傳入enumerate()函式，得到一個enumerate物件：
```python==
my_list = ['apple', 'banana', 'orange']
enumerate_list = enumerate(my_list)
```

2. 可以使用for迴圈來迭代enumerate物件：

```python==
for index, value in enumerate_list:
    print(index, value)
```
執行結果
```python==
0 apple
1 banana
2 orange
```

* 實作
(取卡登活動列表，濾掉長榮倍數引擎活動後，取第一筆活動進行登錄)

1. 取卡登活動列表
```python==
unregisteredActivities = [
    {
        "notice": "1.倍數引擎活動期間至2023/12/31。2.海外消費係指交易地點非臺灣之一般交易。3.每次航程限單筆消費，不得分刷。4.每次航程及每筆機票∕自由行∕團費消費限登錄乙次。5.年度哩程回饋上限請詳閱官網說明。6.限時禮遇限2023/12/31前，持指定卡片刷卡且完成請款入帳之長榮官網購票、機上免稅品(預購消費不適用)、海外消費適用，御璽卡不適用。7.詳情請參閱本行官網說明。",
        "registrationStatus": "UNREGISTERED",
        "startDate": "2023/01/01",
        "endDate": "2023/12/31",
        "remainingDays": "8",
        "name": "長榮航空聯名卡啟動倍數引擎",
        "description": "刷長榮航空聯名極致無限卡/無限卡/極致御璽卡，搭乘長榮/立榮航空實際營運之國際線航班，並於搭乘後5~180天內完成登錄，即啟動倍數引擎，享指定消費類別NT$10=1哩。\r\n※限時禮遇：2023/12/31前刷本活動指定卡片且完成請款入帳之長榮官網購票、機上免稅品(預購消費不適用)、海外消費，無需登錄倍數引擎，即享NT$10=1哩(以上活動御璽卡不適用。完整活動說明請參閱官網)",
        "pid": "0611190A",
        "url": "https://www.cathaybk.com.tw/cathaybk/Personal/Credit-Card/Cards/Intro/eva/login",
        "seqNo": None
    },
    {
        "notice": "0829熱門<br/>\n1.\t未滿20歲之KOKO簽帳金融卡持卡人，參與本活動之同時視同已事先取得其法定代理人之允許。 2.\t適用卡別：持有連結KOKO數位帳戶之KOKO簽帳金融卡持卡人，且無同時持有KOKO COMBO icash聯名卡者。 3.\tKOKO簽帳金融卡之指定超商/交通/影音娛樂/運動健身消費享3%現金回饋(含原一般消費1.2%現金回饋)，每戶每月指定回饋上限NT$200(回饋上限為歸戶下所持有的所有KOKO簽帳金融卡合併計算)，指定消費回饋超出回饋上限NT$200之部分，僅享一般消費1.2%現金回饋(回饋無上限)。 4.\t本活動指定通路回饋之消費日期於同一月份(每月1日至當月最後1日)之指定消費金額合併計算後四捨五入，歸戶每月指定回饋上限NT$200。例如：2022/3/1-2022/3/31為一",
        "registrationStatus": "UNREGISTERED",
        "startDate": "2023/08/29",
        "endDate": "2024/03/30",
        "remainingDays": "8",
        "name": "0829熱門",
        "description": "0829熱門-已開放登錄 完成活動登錄後， KOKO簽帳金融卡當期之指定超商/交通/影音娛樂/運動健身 消費金額享3%現金回饋！(每戶每月帳單回饋上限NT$200)",
        "pid": "O230825E",
        "url": "",
        "seqNo": None
    }
]

unregistered_activities = unregisteredActivities

```

2. 使用for迴圈來迭代enumerate物件
```python==
for index, activity in enumerate(unregisteredActivities):
    print(index, activity)

```
執行結果
```python==
0 {'notice': '1.倍數引擎活動期間至2023/12/31。2.海外消費係指交易地點非臺灣之一般交易。3.每次航程限單筆消費，不得分刷。4.每次航程及每筆機票∕自由行∕團費消費限登錄乙次。5.年度哩程回饋上限請詳閱官網說明。6.限時禮遇限2023/12/31前，持指定卡片刷卡且完成請款入帳之長榮官網購票、機上免稅品(預購消費不適用)、海外消費適用，御璽卡不適用。7.詳情請參閱本行官網說明。', 'registrationStatus': 'UNREGISTERED', 'startDate': '2023/01/01', 'endDate': '2023/12/31', 'remainingDays': '8', 'name': '長榮航空聯名卡啟動倍數引擎', 'description': '刷長榮航空聯名極致無限卡/無限卡/極致御璽卡，搭乘長榮/立榮航空實際營運之國際線航班，並於搭乘後5~180天內完成登錄，即啟動倍數引擎，享指定消費類別NT$10=1哩。\r\n※限時禮遇：2023/12/31前刷本活動指定卡片且完成請款入帳之長榮官網購票、機上免稅品(預購消費不適用)、海外消費，無需登錄倍數引擎，即享NT$10=1哩(以上活動御璽卡不適用。完整活動說明請參閱官網)', 'pid': '0611190A', 'url': 'https://www.cathaybk.com.tw/cathaybk/Personal/Credit-Card/Cards/Intro/eva/login', 'seqNo': None}
1 {'notice': '0829熱門<br/>\n1.\t未滿20歲之KOKO簽帳金融卡持卡人，參與本活動之同時視同已事先取得其法定代理人之允許。 2.\t適用卡別：持有連結KOKO數位帳戶之KOKO簽帳金融卡持卡人，且無同時持有KOKO COMBO icash聯名卡者。 3.\tKOKO簽帳金融卡之指定超商/交通/影音娛樂/運動健身消費享3%現金回饋(含原一般消費1.2%現金回饋)，每戶每月指定回饋上限NT$200(回饋上限為歸戶下所持有的所有KOKO簽帳金融卡合併計算)，指定消費回饋超出回饋上限NT$200之部分，僅享一般消費1.2%現金回饋(回饋無上限)。 4.\t本活動指定通路回饋之消費日期於同一月份(每月1日至當月最後1日)之指定消費金額合併計算後四捨五入，歸戶每月指定回饋上限NT$200。例如：2022/3/1-2022/3/31為一', 'registrationStatus': 'UNREGISTERED', 'startDate': '2023/08/29', 'endDate': '2024/03/30', 'remainingDays': '8', 'name': '0829熱門', 'description': '0829熱門-已開放登錄 完成活動登錄後， KOKO簽帳金融卡當期之指定超商/交通/影音娛樂/運動健身 消費金額享3%現金回饋！(每戶每月帳單回饋上限NT$200)', 'pid': 'O230825E', 'url': '', 'seqNo': None}
```

3. 將長榮倍數引擎活動濾掉
```python==
for index, activity in enumerate(unregisteredActivities):
    if activity['pid'] == "0611190A":  # 過濾掉 長榮倍數引擎卡登活動 pid = 0611190A
        unregistered_activities.pop(index)
        print(index, activity)
        break
```

執行結果
(因為for迴圈在第一筆就找到倍數引勤活動，濾掉就跳出來了)
```python==
{'notice': '0829熱門<br/>\n1.\t未滿20歲之KOKO簽帳金融卡持卡人，參與本活動之同時視同已事先取得其法定代理人之允許。 2.\t適用卡別：持有連結KOKO數位帳戶之KOKO簽帳金融卡持卡人，且無同時持有KOKO COMBO icash聯名卡者。 3.\tKOKO簽帳金融卡之指定超商/交通/影音娛樂/運動健身消費享3%現金回饋(含原一般消費1.2%現金回饋)，每戶每月指定回饋上限NT$200(回饋上限為歸戶下所持有的所有KOKO簽帳金融卡合併計算)，指定消費回饋超出回饋上限NT$200之部分，僅享一般消費1.2%現金回饋(回饋無上限)。 4.\t本活動指定通路回饋之消費日期於同一月份(每月1日至當月最後1日)之指定消費金額合併計算後四捨五入，歸戶每月指定回饋上限NT$200。例如：2022/3/1-2022/3/31為一', 'registrationStatus': 'UNREGISTERED', 'startDate': '2023/08/29', 'endDate': '2024/03/30', 'remainingDays': '8', 'name': '0829熱門', 'description': '0829熱門-已開放登錄 完成活動登錄後， KOKO簽帳金融卡當期之指定超商/交通/影音娛樂/運動健身 消費金額享3%現金回饋！(每戶每月帳單回饋上限NT$200)', 'pid': 'O230825E', 'url': '', 'seqNo': None}
```
4. 取第一筆卡登活動的pid
```python==
print(unregistered_activities[0]['pid'])
# O230825E
```