---
title: CodeFree|喝一杯咖啡,輕鬆學 Python
date: 2022-07-05
is_modified: false
disqus: cynthiahackmd
image: https://i.imgur.com/ibijtxL.png
categories:
- "程式設計 › 程式語言與架構"
tags:
- "程式設計 › 程式語言與架構"
- "Python"
- "讀書筆記"
- "Hiskio"
---
{%hackmd @CynthiaChuang/Github-Page-Theme %}
<br>
又是喝咖啡學程式系列,這次是學 Python。筆記內容包括[基礎](https://codefree.hiskio.com/courses/27)與[進階](https://codefree.hiskio.com/courses/28)兩堂課。
<!--more-->
<br>
<p class="illustration">
<img src="https://i.imgur.com/ibijtxL.png" alt="hiskio codefree">
Codefree Time(圖片來源: <a href="https://codefree.hiskio.com/">Hiskio Codefree</a>)
</p>
## CH 1|關於 Python 的那些大小事
### 1-1|Python 之父為什麼創造 Python?
這個我知道!聽說是聖誕節的時候太無聊而設計出來的語言,超狂的有沒有!
<p class="illustration">
<img src="https://i.imgur.com/SBmlvxB.png" alt="吉多·范羅蘇姆(Guido van Rossum)">
吉多·范羅蘇姆(Guido van Rossum)(圖片來源: <a href="https://buzzorange.com/techorange/2020/11/17/python-creator-joins-microsoft/">TechOrange 科技報橘</a>)
</p>
Python 之父名為吉多·范羅蘇姆(Guido van Rossum),而 Python 是他在 1989 年聖誕假期時為了打發時間的產物。是說,這位仁兄閒起來有多狂?我上一次看到他的消息就是因為[他說退休太無聊了,準備去微軟打工!](https://buzzorange.com/techorange/2020/11/17/python-creator-joins-microsoft/)
Python 設計哲學是 **「優雅」** 、**「明確」**、**「簡單」**。它將許多的細節隱藏交由直譯器處理,讓程式設計師可以專注於思考程式邏輯而不是具體的實做細節。
有句 Python 的 Slogan:「人生苦短,我用 Python (Love is short, use python)」,這句話也側面說明了 Python 語法簡單與高效。
<p class="illustration">
<img src="https://i.imgur.com/OYD5b2b.png" alt="Python 的 Slogan:人生苦短,我用Python">
人生苦短,我用Python (Love is short, use python)(圖片來源: <a href="https://read01.com/zh-tw/Pzz63ND.html">壹讀</a>)
</p>
另外課程中提到,Python 擁有「可擴充」使用的彈性,我想這應該是在說明它的第三方套件?
#### 測驗與練習
1. **請問下列何者並非為Python的設計哲學**
- [ ] 簡單
- [ ] 明確
- [x] 快速
- [ ] 優雅
### 1-2|程式的開端:向世界說你好!
兩個重點:
1. Python 的標準輸出是 `print()`
1. 輸出內容以引號將其包圍,**雙引號或單引號皆可**,但必須==成對==出現。
<br>
使用 `print()` 螢幕輸出:
```python=
print("Hello World!")
```
結果:
```bash=
Hello World!
```
是說第一個程式寫 Hello World!的傳統是從哪裡來的?
#### 測驗與練習
1. **完成程式缺少的元素**
請觀察以下程式,完成程式缺少的部分並執行。
```bash=
Hello~
```
**答:**
```python=
print("Hello~")
```
<br>
2. **使用 `print()` 新增文字**
承上題(保留上一題的程式),請新增新的 print() 在原有的程式碼下,並輸出「Today is a good day」。
```bash=
Hello~
Today is a good day
```
**答:**
```python=
print("Hello~")
print("Today is a good day")
```
### 1-3|多行輸出:幾個 print 就幾行輸出
Python 在識別程式指令時,是由上往下逐一識別。理論上,呼叫幾次 print 就輸出幾行。
我會說理論上是因為...如果我在輸出內容插了換行符號的話,這到底算幾行?
<br>
**多行輸出指令**
```python=
print("Hello")
print("My name is HiSKIO!")
```
結果:
```bash=
Hello
My name is HiSKIO!
```
#### 測驗與練習
1. **若電腦執行以下程式,請問總共會輸出幾行結果?**
```python=
print("Hi")
print("My name is HiSKIO")
print("Nice to meet you!")
```
- [x] 3行
- [ ] 1行
- [ ] 5行
### 1-4|工程師的小幫手,論註解的重要性
在電腦語言中,註解(comment)是重要的一個組成部分。
在 Clean Code 一書有提到:
<div class="blockquote-center">
<p>
如果一段註解對於理解程式碼沒有幫助,則沒必要為程式碼添加註解。
</p>
</div>
註解雖可以告訴別人你程式碼的目的,也能增強程式可讀性、可維護性,但除了一些合適的註解,如法律、資訊補充、意圖解說與闡釋外,單純使用程式碼就能表達意圖是最好的。如果是因為程式的函式、命名...等原因,讓人無法輕易理解開發者意圖,需花費大把時間寫註解的,可能重寫程式碼比較快 XDDD
等等,這邊不是 clean code 的讀書心得,先回到課程上。總之註解,好的註解可以幫助理解程式,在 Python 中,用 **一個井號 `#`** 做==單行註解==、用 **三個雙引號 `"`** 或 **三個單引號 `'`** 做==多行註解==。
<br>
**註解指令**
```python=
# 這是單行註解
"""
這是多行註解
這是多行註解
這是多行註解
這是多行註解
"""
```
不管是哪種註解方式,註解內容不會執行,因此輸出皆為空白。
#### 測驗與練習
1. **使用「單行註解」符號完成註解**
有一程式需要請你幫忙註解一行程式,請註解程式 `print("Hello World"!)`,其餘照常輸出。
**答:**
```python=
# print("Hello World!")
print("Nice to meet you")
print(1)
```
<br>
2. **運用「多行註解」符號註解程式**
承上題,請利用多行註解方法,註解程式碼,註解內容為「前兩行程式碼」,其餘照常輸出。
**答:**
```python=
'''
print("Hello World!")
print("Nice to meet you")
'''
print(1)
```
### 1-5|你不知道你錯,那就電腦告訴你錯!
當撰寫的程式不符合語法時,會得到程式語法錯誤的錯誤訊息。
```python=
print("Hello"
```
結果:
```bash=
SyntaxError: invalid syntax
```
<br>
另外,錯誤訊息通常會提示錯誤在第幾行附近,甚至是哪個位置,==仔細觀察訊息可以快速排除錯誤==。
```bash=
File "main.py", line 2
if(a=10):
^
SyntaxError: invalid syntax
```
#### 測驗與練習
1. **SyntaxError 代表?**
- [ ] 程式未執行
- [ ] 程式輸出資料有誤
- [x] 程式語法錯誤
## CH 2|創造變數
### 2-1|資料取名字:變數
變數提供具名稱的記憶體儲存空間,具有==唯一性==。
因 Python 的語言**動態型別**特性,在使用該變數前毋須宣告變數,其資料型別會根據被賦值的型別來自動定義。在建立變數時,只須給出變數名稱(`name`),並使用賦值運算子(`=`)進行賦值(`"HiSKIO"`)。範例如下:
```python=
name="HiSKIO"
```
<br>
在訂定變數名稱須遵守 Python 的變數命名規則:
1. 變數首字元須為英文字母或底線字元。
2. 除首字元外,其他字元僅能為英文字母、底線字元或數字。
3. 不能是保留字,類似 int 之類的。
其他的大、小蛇式命名法...之類的使用規則應該算是 Coding Style?可以看看我之前寫的 [Python Coding Style](https://hackmd.io/@CynthiaChuang/Python-Coding-Style#Naming-Conventions)。至於課程中提到的**以「使用目的」去命名**,這...應該不算命名規則,這是命名常識吧 XDDD
#### 測驗與練習
1. **良好的變數命名習慣有助於整體程式更有架構,在閱讀時也能更方便。請觀察程式,選擇變數「today」儲存資料值為何?**
```python=
name="HiSKIO"
color="blue"
today="Saturday"
```
- [ ] HiSKIO
- [x] Saturday
- [ ] blue
### 2-2|變數的輸出
使用變數最大的好處是,當需要運用該資料時,可以直接呼叫變數名稱得到該值,毋須重複撰寫資料內容與計算。
<br>
**輸出儲存於 name 這個變數的內容**
```python=
name="HiSKIO"
print(name)
print(name)
print(name)
```
結果:
```bash=
HiSKIO
HiSKIO
HiSKIO
```
<br>
若改動變數內資料,則輸出結果也會跟著變動。舉例來說將 `name` 值由 「HiSKIO」 改成 「Hi」,結果如下:
```python=
name="Hi"
print(name)
print(name)
print(name)
```
結果:
```bash=
Hi
Hi
Hi
```
<br>
引用變數時必須完全正確。若引用錯誤會被視為使用未宣告變數,因而找不到對應資料輸出,出現 **NameError** 的錯誤。
```python=
name="HiSKIO"
print(nam)
```
結果:
```bash=
NameError: name 'nam' is not defined
```
<br>
若要做資料拼接,可在輸出時使用逗號來拼接變數。
```python=
name="HiSKIO"
print("My name is" , name)
```
結果:
```bash=
My name is Hiskio
```
<br>
若使用多個逗號,在輸出時會依照順序,由左至右疊加。
```python=
name="HiSKIO"
print("My name is" , name , "nice to meet you" , "!")
```
結果:
```bash=
My name is HiSKIO nice to meet you !
```
<br>
說到做字串拼接,如果複雜點的字串我應該會用**字串格式化**或是**字串插值**的方法,這兩個寫起來可讀性比較好,就是得注意一下 Pytnon 版號。
```python=
host="HiSKIO"
visitor="Cynthia"
## 字串格式化
print("Hello {visitor}. My name is {host}, nice to meet you !".format(visitor=visitor, host=host))
## 字串插值
print(f"Hello, {visitor}. My name is {host}, nice to meet you !")
```
結果:
```bash=
Hello Cynthia. My name is HiSKIO, nice to meet you !
Hello Cynthia. My name is HiSKIO, nice to meet you !
```
#### 測驗與練習
1. **請觀察程式,請問輸出為何者?**
```python=
name="HiSKIO"
print("Hello",name,"!")
```
- [x] Hello HiSKIO !
- [ ] Hello name !
## CH 3|資料型態
### 3-1|Python 世界中的資料型態與種類
Python 資料型別有以下幾種:
1. 數值型態(Numeric):int, float, bool, complex
2. 字串型態(String):str, char
3. 容器型態(Container):list, set, dict, tuple
<br>
其中比較常用的資料型態,如下:
| 中文 | 英文| 說明 |舉例|
| -------- | -------- | -------- | -------- |
| 文字 | string | 用引號包圍的資料內容 | `"Hello~Hiskio!"` `'Hi~'` |
| 整數 | int | 常見的阿拉伯數字 | `5` |
| 浮點數 | float | 含小數的阿拉伯數字 | `0.23`|
| 布林值 | boolean | True or False,首字母大寫 |`True`|
| 串列 | list | 具備順序性的集合 | `["apple","orange","pineapple","grape"]`|
| 字典 | dictionary | 由鍵(key)和值(value)構成 | `{"name":"王小明","id":249,"age":22}`|
#### 測驗與練習
1. **請觀察程式,並選擇變數 number 儲存的資料型態為何?**
```python=
number="5"
```
- [x] 文字
- [ ] 數字
- [ ] 布林值
### 3-2|資料型態:文字
在賦值文字變數時,可使用引號來表字串的資料型態,雙引號 `""` 或單引號`''` 都行,Python 沒有用這個來區分字串或字元。
像我自己習慣最外層是雙引號,我同事的話則是保留 C 習慣,字元用單引號、字串用雙引號,反正整個專案記得統一就好,~~不統一也不會怎樣,就是逼死處女座而已~~。
若引號內沒有任何資料,則稱為空字串。
```python=
id="" #變數id的資料值等於空,因為雙引號內無任何資料
print(id) #輸出無任何資料
```
<br>
字串可透過加號由左至右拼接。
```python=
name="HiSKIO"+"!"
print(name)
```
結果:
```bash=
HiSKIO!
```
<br>
教材中說到,**對於數學四則運算符號(`+ - * /`),文字只支援「加號」符號**。我想它這句話的意思,是說只有加號能支援被加數跟加數都是文字,其他的運算符號無法,會直接迸出 **TypeError**。
但若是被乘數是文字、乘數是數字,這情況是成立的:
```python=
say1 = "重要的事要說三次!"
say3 = say1 * 3
print(say3)
```
結果:
```bash=
重要的事要說三次!重要的事要說三次!重要的事要說三次!
```
#### 測驗與練習
1. **以變數設立字串**
請用變數 color 設立一個字串,儲存「blue」並輸出變數 color。
**答:**
```python=
color="blue"
print(color)
```
<br>
2. **使用加號完成文字相加**
請設計一道程式,觀察以下執行後的結果格式,將文字相加,變數 color 與 data 分別儲存「blue」與「book」。
**答:**
```python=
color="blue"
data="book"
print(color+data)
```
### 3-3|資料型態:數字
Python 常見的數字型態有整數 int 和浮點數 float 兩種。跟其他語言不同,Python 浮點數並沒有單雙精度,也就是 float 與 double,的區別。不過 Python 中的 float 與其他程式語言中的 double 具有相同的精度。
兩兩數字資料型態可以任意使用四則運算符號進行運算,不過當整數和浮點數互相運算時得出結果會是浮點數。
```python=
a=8
b=5.5
print(type(a+b))
```
結果:
```bash=
<class 'float'>
```
<br>
對了課程中沒提及,這些運算符號稱為 **運算子(operator)**,而用來算術計算的被特稱為 **算術運算子(arithmetic operator)** ,而常見的算術運算子除四則運算符號外,還包括取商數、取餘數跟次方三種。
| 運算子 | 功能 | 範例 |
| -------- | -------- | -------- |
| + | 加 |`a + b #8+5=13`|
| - | 減 |`a - b #8-5=3`|
| * | 乘 |`a * b #8*5=40`|
| / | 除 |`a / b #8/5=1.6`|
| // | 取商數 |`a // b #8//5=1`|
| % | 取餘數 |`a % b #8%5 取餘數 3`|
| ** | 指數 |`a ** b #8的5次方=32768` |
上述這種==運算式(expression)是由兩個運算元(operand)與一個運算子所構成==。最後的計算結果可依需求直接輸出、賦值到新的變數或寫回原變數。
```python=
a=8
#直接輸出
print(a+3) #11
#賦值到新的變數
c=a+3 #c=11
#寫回原變數
a=a+3 #a=11
```
如果是寫回原變數,可省略被運算元,將運算子後面加上 `=`:
```python=
a+=3 #a=11
```
<br>
進行除法運算時,得注意除數不得為 0。在數學上除以 0 沒有意義,但在電腦中除以 0 它會直接掛給你看:
```python=
print(10/0)
```
結果:
```bash=
ZeroDivisionError: division by zero
```
恩...好像也不一定直接掛,看語言跟資料型別吧。像是 Java 除以 0 也是得 error、除以 0.0 會得 infinity、0 除以 0 則會得到 NaN。Javascript 好像也是,不過 Python 必掛掉就是了。
#### 測驗與練習
1. **有兩個變數 a 與 b,分別儲存 7 和 9,請觀察輸出結果,找出使用的四則運算符號**
```python=
a=7
b=9
```
輸出結果
```python=
-2 40353607
```
- [ ] `a-b , a*b`
- [ ] `a+b , a%b`
- [ ] `a+b , a//b`
- [x] `a-b , a**b`
## CH 4|流程控制
### 4-1|識別程式碼的好夥伴 — 縮排
Python 是個採用**越位規則** :soccer: 的程式語言。該種語言是透過縮排來表示區塊,而非大括號或關鍵詞來確定結構;也就是說,在 Python 中 ==同樣的縮排代表其程式是同一個區塊==。因此當你縮排錯誤,Python 會毫不留情地給你報錯:
```python=
print("Hello~")
print(1)
```
結果:
```bash=
IndentationError: unexpected indent
```
<br>
在課程中它是 **Tab** 來縮排,不過要注意的是 Tab 在不同的環境、不同的編輯器開啟,所呈現的效果會不同,可能會被展開成空格,有的不會,即便展開成空格也有 4 個或 8 個的長度區別。記得有一次進 code 就是因為這樣產生了 conflict。
<br>
所以你說我是空白派的嗎?其實不算,因為我習慣按 Tab 縮排;但你說我是 Tab 派的嗎?也不算,因為我會習慣調整 IDE 讓它在按下 Tab 時插入 4 個空格。不管哪一派,反正你統一一種用就是了。
雖然我記得看過人家的[實驗](https://iter01.com/92400.html)兩種混用是也行,就是得算好 Tab 跟空格的數量,但如果你真的這樣搞絕對會被其他開發者爆打的 XDDD
<p class="illustration">
<img src="https://i.imgur.com/Ayg8TPb.png" alt="縮排,Tab 還是空格?">
縮排,Tab 還是空格?(圖片來源: <a href="https://mobile.twitter.com/_naidile">Naidile (@_Naidile) / Twitter</a>)
</p>
#### 測驗與練習
1. **請選出縮排的使用用意與對應的鍵盤按鍵**
- [ ] 用意:區分程式碼、對應按鍵:Backspace
- [ ] 用意:成立流程控制、對應按鍵:Tab
- [x] 用意:區分程式碼、對應按鍵:Tab
### 4-2|if 流程控制
if 的流程控制簡單來說就是==如果符合什麼條件就去做什麼動作==。而在程式語言書寫方面,會有**條件式**、**冒號**與**縮排**等元素,一旦括號內條件成立時,則執行縮排內的程式。
```python=
if(設立條件):
#達成條件下的狀況
```
以一個生活化的例子來說:「如果期中考數學考了100分,媽媽就會獎勵我一塊雞排」,將它撰寫成虛擬碼則會變成:
```python=
if(期中考數學考100分):
print("獎勵雞排")
```
<br>
在進行條件判斷時會用到 **關係運算子(Relational operator)** 或稱 **比較運算子(Comparison operator)** 來比較兩數間的關係。
| 關係運算子 | 意義 | 使用範例 | 範例運算結果 |
| ---------- | -------- | -------- |:------------:|
| == | 等於 | 1+1 == 2 | True, 1 |
| != | 不等於 | 3 != 4 | True, 1 |
| > | 大於 | 5 > 6 | False, 0 |
| >= | 大於等於 | 7 >= 8 | False, 0 |
| < | 小於 | 9 < 10 | True, 1 |
| <= | 小於等於 | 10 <= 10 | True, 1 |
將前面的虛擬碼用關係運算子來撰寫的話會變成:
```python=
score=100
if(score==100):
print("獎勵雞排")
```
現在寫習慣了是還好,但剛開始學寫程式的時候常常把等於的運算子打成 `=`,每次都 debug 好久 XDDD
<br>
說到錯誤,這部分在撰寫時常見的錯誤不外乎是**少冒號**或**縮排錯誤**,不過這些錯誤都能從錯誤訊息得知:
```python=
score=100
if(score==100)
print("獎勵雞排")
```
結果:
```bash=
File "main.py", line 2
if(score==100)
^
SyntaxError: invalid syntax
```
<br>
或是
```python=
score=90
if(score==100):
print("獎勵雞排")
#90分未符合,但無縮排故都會輸出
```
結果:
```bash=
File "main.py", line 3
print("獎勵雞排")
^
IndentationError: expected an indented bloc
```
#### 測驗與練習
1. **使用 if 流程控制判斷餘數**
請設計一支程式,設立兩個整數變數 a 與 b , a 與 b 分別儲存 10 與 5 判斷兩個變數相除(a/b)餘數是否為 0 ,若餘數為 0,輸出餘數為 0。
**答:**
```python=
a=10
b=5
#a除以b的餘數等於多少為整除~,注意if架構符號
if(a % b == 0):
print("餘數為0")
```
### 4-3|else 例外處理
有 if 怎麼會沒有 else 呢 XDDD
在未達成條件時,也有觸發相對應的情況,因此可以用 else 來控制程式。
```python=
score=100
if(score==100):
print("獎勵雞排")
else:
print("沒獎勵~")
```
結果
```bash=
獎勵雞排
```
#### 測驗與練習
1. **else 例外情況**
承上單元實作練習,請設計一支程式,設立兩個整數變數 a 與 b , a 與 b 分別儲存 11 與 5,判斷兩變數餘數是否為 0,若兩整數相除後餘數為 0,輸出餘數為 0 ;若兩整數相除後餘數不為 0,請輸出餘數不為 0。
**答:**
```python=
a=11
b=5
if(a%b==0):
print("餘數為0")
else:
print("餘數不為0")
```
### 4-4|elif 多重流程控制判斷
不過現實生活並非非黑即白,是會出現許多的可能。例如:媽媽說考 100 分,獎勵雞排;若沒有 100 分但有 90 分以上,就獎勵杯珍珠奶茶:連 90 分都沒有就只能空手而回了。
這種情境下 `if...else...` 可能會不好使,改使用多重判斷的 `elif` 會是比較好的選擇:
```python=
score=95
if(score==100):
print("獎勵雞排")
elif(score>=90):
print("獎勵珍珠奶茶")
else:
print("沒有獎勵")
```
電腦在進行判讀時,是由上往下執行:
- step 1:先判斷 score 是否等於 100,達成條件就停止判斷,沒有達成條件則往下繼續執行。
- step 2:是否大於等於 90,達成則不會繼續往下執行。
- step 3:皆無達成上述條件,停止執行。
#### 測驗與練習
1. **符號多重條件判斷**
請幫忙設計一個計算機程式,判斷變數 notation 中儲存的四則運算符號,變數 notataion 儲存為「+」。
若 notation 儲存為「+」,則輸出「符號:加」;notation儲存為「-」,則輸出「符號:減」;notation儲存為「*」,則輸出「符號:乘」;notation儲存為「/」,則輸出「符號:除」
**答:**
```python=
notation="+"
if(notation=="+"):
print("符號:加")
elif(notation=="-"):
print("符號:減")
elif(notation=="*"):
print("符號:乘")
elif(notation=="/"):
print("符號:除")
```
嘖嘖,Python 沒有 Swich-case 可以用。
### 4-5|巢狀 if 流程控制
多層的條件判斷可稱為**巢狀 if 流程控制**,簡單來說來說,就是在條件成立後再做另一層條件判斷。在寫這種結構的時候,更需要注意同樣縮排的程式碼為同一區塊,當然冒號也別忘了:
```python=
if(條件1):
#達成條件1的情況
if(條件1-1):
#達成條件1和條件1-1的情況
else(條件1-2):
#達成條件1和條件1-2的情況
```
是說,如果你覺得巢狀多到難以閱讀,或是已經會混淆縮排的狀況,真心建議重構你的程式碼 XDDD
<br>
一樣來個傷媽媽荷包的範例:「若媽媽規定期中考數學考 100 分而且國文也考 100 分,就獎勵雞排和泡芙。」
```python=
math_score=100
chinese_score=100
# Step1
if(math_score==100):
# Step2
if(chinese_score==100):
print("獎勵雞排和泡芙")
# Step3
print("數學分數達成,但國文分數並未達成")
```
是說,它的範例程式碼有點問題。如果這樣寫最終輸出結果會是:
```bash=
獎勵雞排和泡芙
數學分數達成,但國文分數並未達成
```
因為它 Step3 那行輸出並沒任何條件判斷,換句話說只要達成 Step1 的條件後,Step3 就一定會輸出。如果按照題意改的話,應該要多加一個 else:
```python=
math_score=100
chinese_score=100
# Step1
if(math_score==100):
# Step2
if(chinese_score==100):
print("獎勵雞排和泡芙")
# Step3
else:
print("數學分數達成,但國文分數並未達成")
```
#### 測驗與練習
1. **巢狀 if 流程控制判斷贈品**
請設計一支程式判斷,消費者是否得到贈品,變數 totalcash 與 purchase 分別儲存「1000」與「鳳梨」,規則如下:
- 若消費者購買金額達「1000元」,而且購買物為「鳳梨」,則輸出「環保購物袋」
- 若消費金額未達 1000 元,則直接輸出「無贈品」
**答:**
```python=
totalcash=1000
purchase="鳳梨"
if(totalcash==1000 and purchase=="鳳梨"):
print("環保購物袋")
else:
print("無贈品")
```
呃...寫完才發現不合題意,沒用巢狀結構。算了不理它了。
### 4-6|符號 and 與 or
像剛剛那種簡單條件判斷,很少會把它拆成巢狀來寫,更多時候會用**邏輯運算子(Logical operators)**,來釐清所有條件之間的關係。常用的邏輯運算子有`and`、`or` 和 `not` 三種,運算的結果不是 `True` 就是 `False`。
<br>
讓我們繼續獻祭媽媽的錢包
- **條件皆達成**: 數學考100分 而且(and) 國文考100分 → 獎勵雞排和泡芙
- **條件其一達成**: 數學考100分 或者(or) 國文考100分 → 獎勵雞排
```python=
if(math_score==100 and chinese_score==100):
print("獎勵雞排和泡芙")
elif(math_score==100 or chinese_score==100):
print("獎勵雞排")
```
<br>
題外話,如果兩邊運算元都是布林值的情況下,這時 `and` 跟 `or` 會跟位元運算子的 `&` 和 `|` 等價。不過還是別這麼做會比較好,小心把自己給搞混了。
- [Python Tips: and, or, &, | 的差別](https://killer0001.blogspot.com/2018/10/python-tips-and-or.html)
- [Python 中 (&,|)和(and,or)之間的區別](https://kknews.cc/code/mn9ggj2.html)
#### 測驗與練習
1. **使用 and 或 or 符號完成流程控制判斷**
請設計一支程式判斷,根據下列規則,判斷消費者得到贈品的狀況,變數 totalcash 與 purchase 分別儲存「1000」與「葡萄」,並善用 and 與 or 的用法。
- 若購買金額達「1000元」,而且購買物為「鳳梨」,兩者皆達成則輸出「環保購物袋」
- 若購買金額達「1000元」,或者購買物為「鳳梨」,達到其中一個規則,則輸出「鳳梨軟糖一顆」
- 若上述規則皆未達到,則輸出「無贈品」
**答:**
```python=
totalcash=1000
purchase="葡萄"
if(totalcash==1000 and purchase=="鳳梨"):
print("環保購物袋")
elif(totalcash==1000 or purchase=="鳳梨"):
print("鳳梨軟糖一顆")
else:
print("無贈品")
```
## CH 5|for 迴圈
### 5-1|迴圈介紹
另一種常見的控制流程方法是**迴圈**,它在程式中只被撰寫一次,但可能會==重複執行數次==。在 Python 中實作迴圈的方式有 for 迴圈和 while 迴圈兩種。
<br>
不過實作迴圈前,這邊先來介紹迴圈控制的指令 `break` 與 `continue`:
- **break**:打破迴圈,強制跳出**整個**迴圈。
- **continue**:停止**本次**迴圈動作,但迴圈整體沒有結束,繼續進入下一輪。
另外還有一個比較少用的指令 `pass`,它是 do nothing 的概念。我自己都拿它搭配 TODO 的註解來使用來。
#### 測驗與練習
1. **下列迴圈重要指令當中,何者是在迴圈指令當中,直接打破迴圈,使程式強制跳出迴圈?**
- [x] break
- [ ] for loop
- [ ] continue
### 5-2|無窮迴圈
<div class="blockquote-center">
<p>
注意迴圈執行狀況,勿出現無窮迴圈的情況。
</p>
</div>
什麼是無窮迴圈?就是讓==迴圈永遠執行==就叫無窮迴圈。通常發生**終止條件未設定好**,導致迴圈不斷執行無法停止動作,最終會導致電腦記憶體不足而發生當機的情況。
所以撰寫迴圈時,請確定程式中至少有個地方是會讓迴圈終止。不過說是這麼說啦,通常寫迴圈都會有終止條件,但偏偏中間做運算的時候出了差錯,導致無窮迴圈的產生,這種情況就真的很難抓蟲呀...
#### 測驗與練習
1. **請選出導致電腦發生「無窮迴圈」的情況**
- [x] 沒有設定好迴圈的條件,電腦不知道什麼時候要停止重複的動作
- [ ] 有設定好迴圈的條件,電腦明確知道什麼時候要停止重複的動作
### 5-3|for 迴圈架構:(首項、末項、差值)
在 for 迴圈的架構中會存在一個迴圈變數-**初始值、條件、遞增值**,使在疊代過程中能知曉執行順序。不過在課程中,初始值、條件、遞增值三個詞它使用的**首項、末項、差值**:
```python=
for i in range(首項,末項,差值):
#要重複執行的指令
```
<br>
常見的次數控制型迴圈多會搭配 `range` 來函數使用,在函數中會定義首項、末項與差值的參數:
- **首項**
初始值。迴圈的起始點,也就是變數 i 的起始數字,預設為 0。例如 `range(0,5)` 等價於 `range(5)`。
- **末項**
條件。迴圈結束的條件,在差值為正時,當變數 i 大於等於該值即會終止迴圈,因此終點值是不會執行的!舉例來說,`range(0,5)` 是 [0, 1, 2, 3, 4] 沒有 5。
- **差值**
遞增值。每一輪迴圈結束後,變數 i 會加上此差值,作為下一輪迴圈的變數值,預設為 1。因此, `range(0,5,1)` 等價於 `range(0,5)`。
<br>
實際執行結果如下:
```python=
for i in range(0,3,1):
print(i)
```
人工直譯的話其過程如下:
| 起始值給變數 i | 確認變數 i 是否小於末項 | 執行輸出 | 賦予差值給變數 i |
| -------------- | ----------------------- | ---------- | ---------------- |
| i=0 | i<3(成立則繼續) | print(0) | i=0+1=1 |
| i=1 | i<3(成立則繼續) | print(1) | i=1+1=2 |
| i=2 | i<3(成立則繼續) | print(2) | i=2+1=3 |
| i=3 | i<3(不成立則結束回圈) | 已跳出程式 | 已跳出程式 |
因此最終輸出:
```bash=
0
1
2
```
<br>
在課程中提到,當迴圈的**首項一定要小於末項**。因為當首項大於末項且差值為1時,是沒有辦法執行該迴圈的,因為首項大於末項使終止恆成立,則無法進入迴圈。
其實這句話不完全正確,當首項大於末項且差值為正數時,的確無法執行迴圈。但差值也可為負數,這樣就會是一個遞減型的計數器,只是要稍微注意一下==末項的判斷條件會與正數剛好相反==。舉例來說,`range(0,5,1)` 是當變數**大於等於** 5 時,即會終止迴圈;`range(5,0,-1)` 則是變數**小於等於** 0 時,終止迴圈。
#### 測驗與練習
1. **以「range」控制迴圈執行**
請設計一支程式,利用 for 迴圈,首項為 1、末項為 8、差值為 2,執行並輸出每一次迴圈中執行的結果。
**答:**
```python=
for i in range(1,8,2):
print(i)
```
<br>
2. **觀察 for 迴圈程式執行結果並完成程式改寫**
承上題,若輸出規律變為如下,請觀察以下輸出規律,並利用 for 迴圈完成程式撰寫。
- 每一行兩數字間有一空格,使用逗點輸出變數
- 觀察每一行兩個輸出內容之間的數學關係(加、減、乘、除、商、餘、指數)
```bash=
1 1
3 9
5 25
7 49
```
**答:**
```python=
for i in range(1,8,2):
print(i,(i**2))
```
### 5-4|for 迴圈裡的流程控制
迴圈可以搭配 if 條件判斷使用,在迴圈裡面設立條件以控制迴圈。
```python=
for i in range(0,5,1):
if(i==2):
break
print(i)
```
結果:
```bash=
0
1
```
<br>
另一個迴圈控制指令 `continue` 的效果如下:
```python=
for i in range(0,5,1):
if(i==2):
continue
print(i)
```
結果:
```bash=
0
1
3
4
```
不同於 `break` 的直接結束迴圈,`continue` 只是停止本次迴圈動作,繼續進入下一輪。因此會看到一個遇到 3 時,輸出就停止了;另一個則是跳過不輸出 3。
#### 測驗與練習
1. **以 break/continue 控制 for 迴圈**
請改寫下列程式,新增一個 if 流程控制當控制迴圈的變數 i 為 5 時,跳過當次輸出,其餘正常輸出。
**答:**
```python=
for i in range(1,10,1):
if(i==5):
continue
print(i)
```
### 5-5|巢狀 for 迴圈
跟巢狀 if 流程一樣,多層的 for 迴圈稱為**for 巢狀迴圈**。撰寫的時候除了一樣要注意縮排外,另外要注意的是變數的作用域,外層迴圈的變數會作用於內層迴圈之中,因此==不同層的迴圈必需要用不同的變數去控制迴圈==,否則兩者控制變數會被互相覆寫。
```python=
for i in range(3,5,1):
for j in range(0,3,1):
print(i,j)
```
再來當一次人工直譯器:
| 外層變數 i | i<5? | 內層變數 j | j<3? |
| ------------ | ---- | ------------ | ---------------------- |
| i=3 | 成立 | j=0 | 成立 |
| | | j=1 | 成立 |
| | | j=2 | 成立 |
| | | j=3 | 不成立則跳出內層迴圈 |
完成內層後,回到外層重新賦值變數 i ,重新進入內層迴圈,再一次以 `range(0,3,1)` 執行:
| 外層變數 i | i<5? | 內層變數 j | j<3? |
| ---------- | ---- | ---------- | -------------------- |
| i=4 | 成立 | j=0 | 成立 |
| | | j=1 | 成立 |
| | | j=2 | 成立 |
| | | j=3 | 不成立則跳出內層迴圈 |
最終輸出結果如下:
```bash=
3 0
3 1
3 2
4 0
4 1
4 2
```
#### 測驗與練習
1. **觀察程式執行後的結果完成缺少的巢狀 for 元素**
請觀察輸出範例,觀察輸出數字,並根據提示程式碼填寫遺漏的程式碼。
```python=
for i in range(0,,1): #少了末項數字該寫什麼呢?
for j in range(0,,1): #少了末項數字該寫什麼呢?
print(i,j)
```
輸出數字:
```bash=
0 0
0 1
1 0
1 1
2 0
2 1
```
**答:**
```python=
for i in range(0,3,1): #少了末項數字該寫什麼呢?
for j in range(0,2,1): #少了末項數字該寫什麼呢?
print(i,j)
```
## CH 6|while 迴圈
### 6-1|當 while 迴圈條件成立時
除 for 迴圈外,另一種實作迴圈的方式是 while 迴圈,兩者在架構上及用途上大相逕庭。從英文的角度來看,while 的用法可以理解成**當…的時候**,放到 Python 中就是==當括號的條件成立的時候==:
```python=
while(條件判斷):
#要重複執行的指令
```
<br>
不同於 for 迴圈有一個很明顯的計數器的存在,在 while 迴圈中只要判斷條件成立,就會一直執行下去,並沒有執行次數的初始限制在;因此較適合用於==不確定會執行幾次,但只要條件符合就一直執行==的情況。所以在寫 while 迴圈要注意迴圈終止條件的檢查,不然真的很容易搞出無窮迴圈。
```python=
number=3
while(number<8):
print(number)
number+=1
```
結果:
```bash=
3
4
5
6
7
```
#### 測驗與練習
1. **以 while 迴圈完成程式**
請設計一支程式碼,觀察輸出情況並使用 while 迴圈完成程式撰寫。
```bash=
2
4
6
8
```
**答:**
```python=
number=2
#設立while迴圈
while(number<10):
print(number)
number+=2
```
### 6-2|while 迴圈裡的流程控制
在 while 迴圈中有一種寫法是 `while(True)`,它會強迫條件判斷一直成立,此時必須搭配 `break` 來對迴圈進行控制,否則絕對是無窮迴圈 XDDD
```python=
number=0
while(True):
if(number==3):
break
print(number)
number+=1
```
結果:
```bash=
0
1
2
```
<br>
沒有認真去看過 Python 的原始碼,不過就行為來說 `while` 後面的判斷式跟 `bool()` 的行為一樣,有興趣的可以去看看上次[踩的坑](https://hackmd.io/@CynthiaChuang/Python-Bool-Function/)。`while` 只有在下列情況回傳 False 而已,其他狀況都是回傳 True:
1. 傳入 False 值。
2. 傳入 None。
3. 傳入空值,如:空陣列、空列表、空字典、空字串...等。
4. 傳入數字 0 ,資料型態為整數或浮點數都算。
5. 傳入物件類別具有 `__bool __` 或 `__len()__`,且其回傳值為 False 或 0。
所以如果傳入其他的情況,會被視為 `while(True)` 繼續向下執行:
```python=
number=0
while(1): #視為while(True)
if(number==3):
break
print(number)
number+=1
```
結果:
```bash=
0
1
2
```
#### 測驗與練習
1. **使用 if 流程控制 while 迴圈**
請完成下列程式,有一變數 a=5,使用 while(True),在迴圈內每完成一次就讓 a+1,當 a 大於 10 時,則停止迴圈,輸出當下變數 a 的數值。
```bash=
5
6
7
8
9
10
11
```
**答:**
```python=
a=5
#設立while迴圈
while(True):
#判斷是否停止迴圈「continue/break」
if a > 10:
break
print(a)
a += 1
#變動變數a控制迴圈執行狀況
```
題目有點問題,在它要求的輸出結果中有 11,但按文字敘述 a 大於 10 時停止迴圈,不應該列出 11 才對,而它批改的答案中也果然沒有 11。
### 6-3|while 運用
基本上,上述所提到的流程控制,都可以相互使用,只要邏輯成立,就可以使程式順利執行。
讓我們繼續殘害媽媽的錢包:
- 如果數學考試考了 100 分,就會得到 10 張「獎勵雞排兌換卷」
- 若數學分數介於 90~100 之間(不包含 100 分),就會得到 3 張「獎勵雞排兌換卷」
- 若低於 90 分,則「無獎勵」
```python=
math_score=90
if(math_score==100):
number=0
while(number<10):
print(number+1,"獎勵雞排兌換卷")
number+=1
elif(math_score>=90):
number=0
for number in range(0,3,1):
print(number+1,"獎勵雞排兌換卷")
else:
print("無獎勵")
```
#### 測驗與練習
1. **while 迴圈應用練習**
請設計一支程式,使用 while 迴圈執行 20 以內(不含 20)的偶數相加,並以變數 sum 儲存總和,意即 1~19 的所有偶數相加(2、4、8、10、12、14、16、18)。
- 偶數定義:可被2整除(被2除後餘數為0)
- 和為 90
**答:**
```python==
a=0
sum=0
#設立「while迴圈」
while(a<20):
if(a%2==0): #若a為偶數
#sum加總a
sum += a
#變數a做更動以控制while迴圈
a += 1
print(sum)
```
## CH 7|資料型態:串列
### 7-1|串列的架構
串列(list)是一種容器資料型別,可以用來儲存一連串有順序性的元素。例如我們要儲存資料 「hi」、「你好」、「Bonjour」、「こんにちは」、「15」,一共五項資料,換成串列儲存就可以變為:
```python=
# 設定串列的方法:以中括號將儲存的資料前後包起來,並以逗點隔開。
# 變數名稱=[儲存資料內容(用逗點隔開)]
mylist=["hi","你好","Bonjour","こんにちは",15]
print(mylist)
```
結果:
```bash=
['hi', '你好', 'Bonjour', 'こんにちは', 15]
```
#### 測驗與練習
1. **使用中括號完成串列**
請設計一支程式,新增一個串列 fruit 儲存下列水果名稱,並輸出一整個串列。
```bash=
"apple","orange","pineapple","grape"
```
**答:**
```python=
fruit=["apple","orange","pineapple","grape"] #想想看少了什麼串列符號
print(fruit) #輸出一整個串列
```
### 7-2|串列的長度
串列長度有多長,取決於串列內部總共有**多少筆資料**。在 Python 中有提供一函數能快速回傳串列長度:
```python=
len(串列變數名稱)
```
<br>
還是剛剛的串列例子:
```python=
mylist=["hi","你好","Bonjour","こんにちは",15]
print(len(mylist))
```
在串列中一共有 5 筆資料,因此串列長度輸出為 5:
```bash=
5
```
#### 測驗與練習
1. **使用 len() 輸出串列長度**
承上單元題目,請輸出該串列 fruit 的長度,不可以用 `print(4)` 直接輸出。
**答:**
```python=
fruit=["apple","orange","pineapple","grape"]
print(len(fruit))#輸出該串列長度
```
這題目可以!直接輸出 4,害我想到翻轉二元樹的笑話 XDDD
### 7-3|獲取取串列資料
因串列中儲存的資料具備**順序性**,因此若需要獲取串列中的資料時,可以使用**索引值**來提取,第一筆資料由 `0` 開始,以此類推,直到最後一筆。
<p class="illustration">
<img src="https://i.imgur.com/BWUeGIa.png" alt="串列中的索引值">
串列中的索引值(圖片來源: <a href="https://codefree.hiskio.com/courses/28">Codefree - Python 進階篇</a>)
</p>
針對最後一筆資料,除可使用 `總長度-1` 來表示外,也可以直接使用 `-1` 來讀取。
<br>
```python=
mylist=["hi","你好","Bonjour","こんにちは",15]
print(mylist[4])
print(mylist[-1])
```
結果:
```bash=
15
15
```
<br>
如果存取了超過串列長度的索引,會而引起的 **IndexError**:
```python=
mylist=["hi","你好","Bonjour","こんにちは",15]
print(mylist[5])
```
結果:
```bash=
IndexError: list index out of range
```
#### 測驗與練習
1. **透過串列索引值讀取串列資料**
承上單元題目,請輸出串列 fruit 第一個存入的資料。
**答:**
```python=
fruit=["apple","orange","pineapple","grape"]
print(fruit[0])
```
### 7-4|新增串列的資料
如要新增資料到串列中,存在 3 種方法:
- **`.append(新增資料)`**:新增資料至串列最後一筆
```python=
mylist=["hi","你好","Bonjour","こんにちは",15]
mylist.append("안녕")
print(mylist)
```
結果:
```bash=
['hi', '你好', 'Bonjour', 'こんにちは', 15, '안녕']
```
- **`.insert(指定位置,新增資料)`**:新增資料至串列指定位置
```python=
mylist=["hi","你好","Bonjour","こんにちは",15]
mylist.insert(0,"Olá") #指定把資料放到第0個位子
print(mylist)
```
結果:
```bash=
['Olá', 'hi', '你好', 'Bonjour', 'こんにちは', 15]
```
- **`.extend([多筆資料])`**:新增多筆資料至串列後方
```python=
mylist=["hi","你好","Bonjour","こんにちは",15]
mylist.extend(["Olá","안녕"])
print(mylist)
```
結果:
```bash=
['hi', '你好', 'Bonjour', 'こんにちは', 15, 'Olá', '안녕']
```
#### 測驗與練習
1. **新增資料值至串列最後**
請使用新增資料值至串列最後的方法,新增新的資料「peach」至串列 fruit 最後,並輸出一整個串列。
```bash=
['apple', 'orange', 'pineapple', 'grape', 'peach']
```
**答:**
```python=
fruit=["apple","orange","pineapple","grape"]
fruit.append("peach")
print(fruit)
```
<br>
2. **新增資料值至串列指定位置**
承上題,請使用新增資料值至串列指定位置的方法,新增新的資料「guava」至串列 fruit 最初的位子,並輸出一整個串列。
```bash=
['guava', 'apple', 'orange', 'pineapple', 'grape', 'peach']
```
**答:**
```python=
fruit=["apple","orange","pineapple","grape"]
fruit.append("peach")
fruit.insert(0,"guava")
print(fruit)
```
<br>
3. **新增多筆資料值至串列後方**
承上題,請使用新增多筆資料值至串列後方的方法,新增新的資料「tomato」、「lemon」至串列 fruit 最後,並輸出一整個串列。
```bash=
['guava', 'apple', 'orange', 'pineapple', 'grape', 'peach', 'tomato', 'lemon']
```
**答:**
```python=
fruit=["apple","orange","pineapple","grape"]
fruit.append("peach")
fruit.insert(0,"guava")
fruit.extend(["tomato", "lemon"])
print(fruit)
```
### 7-5|刪除串列的資料
有新增就有刪除!不過刪除串列資料的方法則只有 2 種:
- **`del 串列變數名稱[欲刪除資料的位置]`**:刪除串列特定索引值資料
```python=
mylist=["hi","你好","Bonjour","こんにちは",15]
del mylist[0]
print(mylist)
```
結果:
```bash=
['你好', 'Bonjour', 'こんにちは', 15]
#刪除完資料後,會自動遞補資料,因此索引值0為你好
```
- **`.remove(資料內容)`**:刪除串列內指定資料
若存在相同資料時,會砍**最左邊**的,也就是砍索引值小的。
```python=
mylist=["hi","你好","Bonjour","こんにちは",15,"こんにちは"]
mylist.remove("こんにちは")
print(mylist)
```
結果:
```bash=
['hi', '你好', 'Bonjour', 15, 'こんにちは']
```
<br>
如果指定刪除的資料不在串列時,會得到 **ValueError**:
```python=
mylist=["hi","你好","Bonjour","こんにちは",15,"こんにちは"]
mylist.remove("안녕")
print(mylist)
```
結果:
```bash=
ValueError: list.remove(x): x not in list
```
#### 測驗與練習
1. **指定刪除串列的資料**
請利用串列刪除方法,刪除串列 fruit 最後一個資料內容。請使用程式找出最後一個位子,勿輸出 `del fruit[3]`
```bash=
['apple', 'orange', 'pineapple']
```
**答:**
```python=
fruit=["apple","orange","pineapple","grape"]
del fruit[len(fruit)-1]
print(fruit)
```
<br>
2. **刪除串列內特定資料值**
承上題,請刪除串列 fruit 中資料名稱為「pineapple」的資料。
```bash=
['apple', 'orange']
```
**答:**
```python=
fruit=["apple","orange","pineapple","grape"]
del fruit[len(fruit)-1]
fruit.remove("pineapple")
print(fruit)
```
### 7-6|串列綜合運用
請設計一支程式,運用前面章節所學到的串列方法,完成下列實作練習規定:
1. **使用新增串列資料方法新增資料**
運用新增方法新增資料至串列 country 中,資料值為:「Japan」,「India」,「Algeria」,「Brazil」,最後輸出該串列。
**答:**
```python=
country=[]
#1
country.extend(['Japan', 'India', 'Algeria', 'Brazil'])
print(country)
```
<br>
2. **將「該串列長度」資料放至特定位子**
計算串列 country 長度,並將結果新增至串列最一開始的位子,輸出整個串列內容。
**答:**
```python=
country=[]
#1
country.extend(['Japan', 'India', 'Algeria', 'Brazil'])
#2
country.insert(0,len(country))
print(country)
```
<br>
3. **刪除串列規定資料值**
刪除串列最後一個資料值,並輸出該串列。
**答:**
```python=
country=[]
#1
country.extend(['Japan', 'India', 'Algeria', 'Brazil'])
#2
country.insert(0,len(country))
#3
del country[len(country)-1]
print(country)
```
<br>
4. **修改串列資料值**
修改串列索引值第 0 位的資料內容,讀取第 0 位資料值後減 1,並輸出該串列。
**答:**
```python=
country=[]
#1
country.extend(['Japan', 'India', 'Algeria', 'Brazil'])
#2
country.insert(0,len(country))
#3
del country[len(country)-1]
#4
country[0] -= 1
print(country)
```
## CH 8|資料型態:字典
### 8-1|字典架構
字典是 Python 所提供的另一種容器資料型別,在儲存資料時會以鍵(key)和值(value)組合。其中 key 值具備**唯一性**,如果存在相同 key 值,後面會蓋掉前面宣告;但反之 value 值並不具備該特性。因此==有可能會出現一個 key 值對應一個 value 值,但 value 值卻有可能對應多個 key 值==。
```python=
# 儲存資料時會以 key 和 value 組合,以逗點隔開資料,並且使用「大括號」包圍資料。
apple={
"name":"蘋果",
"color":"red",
"number":12,
"variety":["青森蘋果","五爪蘋果","智利蘋果"]
}
print(apple)
```
結果:
```bash=
{'name': '蘋果', 'number': 12, 'color': 'red', 'variety': ['青森蘋果', '五爪蘋果', '智利蘋果']}
```
與串列不同的是,字典並**沒有固定排序**,因此每次執行輸出時的資料順序各不相同;因此,字典通常會用在==不在意排順序的資料上==。
格式上類似 JSON ,兩者都是種結構化資料,皆是利用 key 作為分類關鍵字,將儲存內資料依照各定方式進行分類,這些資料可以是字串、數字、布林、容器資料型別...等資料格式。
:::info
:information_source: **容器資料型別**
在Python中,最常見的容器資料型別有這四個:
- List(串列):一個值可變、可重複、存放有順序性的資料結構。
- Tuple(元組):一個值不可變、可重複、存放有順序性的資料結構。
- Set(集合):一個值可變、不可重複、存放沒有順序性的資料結構。
- Dictionary(字典):一個值可變、可重複、存放沒有順序性且使用唯一 Key的資料結構。
:::
#### 測驗與練習
1. **以字典方式儲存資料**
請設計一支程式儲存關於「人類」的資料值,字典名稱為「people」分類與資料為下,請輸出整個字典內容。
資料內容:
- name :人類
- variety :white,black,yellow
- gender :male,female
- age :0,12,18,45,60
**答:**
```python=
people={
"name":"人類",
"variety":["white","black","yellow"],
"gender":["male","female"],
"age":[0,12,18,45,60]
}
print(people)
```
### 8-2|字典取資料值
因為字典不具備順序性,因此不存在索引值。若要提取字典中的資料,則需透過**直接指定 key** 的方式,來讀取相對應的 value。
```python=
apple={
"name":"蘋果",
"color":"red",
"number":12,
"variety":["青森蘋果","五爪蘋果","智利蘋果"]
}
print(apple["number"])
```
結果:
```bash=
12
```
#### 測驗與練習
1. **讀取字典資料值**
承上單元題目,請輸出鍵(key)為「gender」的資料值。
**答:**
```python=
people={
"name":"人類",
"variety":["white","black","yellow"],
"gender":["male","female"],
"age":[0,12,18,45,60]
}
print(people["gender"])
```
### 8-3|字典新增資料值
也因為它不具備順序性,因此在新增的時候只需要透過新增 key 並賦其 value 值的方式即可。
```python=
apple={
"name":"蘋果",
"color":"red",
"number":12,
"variety":["青森蘋果","五爪蘋果","智利蘋果"]
}
apple["cook"]="apple pie"
print(apple)
```
結果:
```bash=
{'color': 'red', 'number': 12, 'name': '蘋果', 'variety': ['青森蘋果', '五爪蘋果', '智利蘋果'], 'cook': 'apple pie'}
```
#### 測驗與練習
1. **新增資料值至字典中儲存**
承上單元題目,請運用字典新增方式新增下列 key 與 value,並輸出一整個字典內容。
```python=
single:["yes","no"]
```
**答:**
```python=
people={
"name":"人類",
"variety":["white","black","yellow"],
"gender":["male","female"],
"age":[0,12,18,45,60]
}
people["single"]=["yes","no"]
print(people)
```
### 8-4|字典刪除資料值
刪除字典內的資料有 2 種方法,一種是直接呼叫 del,將它從字典中**刪除**:
```python=
apple={"name":"蘋果",
"color":"red",
"number":12,
"variety":["青森蘋果","五爪蘋果","智利蘋果"]
}
del apple["name"]
print(apple)
```
結果:
```bash=
{'color': 'red', 'variety': ['青森蘋果', '五爪蘋果', '智利蘋果'], 'number': 12}
```
另一種則是使用 `pop`,將該值從字典中**彈出**。既然是彈出,就會有回傳值:
```python=
apple={"name":"蘋果",
"color":"red",
"number":12,
"variety":["青森蘋果","五爪蘋果","智利蘋果"]
}
rname=apple.pop("name") #回傳值儲存在變數rname
print(apple)
print(rname)
```
結果:
```bash=
{'color': 'red', 'variety': ['青森蘋果', '五爪蘋果', '智利蘋果'], 'number': 12}
蘋果
```
#### 測驗與練習
1. **刪除字典資料值**
請刪除鍵 key 為「age」的值,並輸出一整個字典與「age」返回之值。
答:
```python=
people={
"name":"人類",
"variety":["white","black","yellow"],
"gender":["male","female"],
"age":[0,12,18,45,60]
}
age=people.pop("age")
print(people)
print(age)
```
## CH 9|函數 function
### 9-1|function 設定格式架構
在寫程式碼的一個重要的觀念是 **Don’t Repeat Yourself**,也就是要儘量**避免相同的程式碼重複出現**,這會降低可讀性很低外,並讓你維護的直升地獄難度。所以此時會進行封裝,達到程式碼的重用。
在 Python 中,若我們要==封裝一段程式邏輯便於其後的使用==時,我們會 function 函式來進行。而函式又分成**內建函式**與**自定義函式** 2 種。
例如說上一章節所使用 `len()`、計算總和 `sum()`、排序 `sorted()` 、取最大值的 `max()`...等,這些都是 Python 中常用的內建函式,可以直接拿來使用:
```python=
score=[88,90,76]
print(sum(score))
```
結果:
```bash=
254
```
<br>
另一種則是我們定義的函式,這可以實做我們想要的邏輯。這邊有個重要的關鍵字 `def`,用來定義即將實做的函式:
<p class="illustration">
<img src="https://miro.medium.com/max/1184/1*dIRdHJL9PgCg8HsCGuJrqQ.png" alt="定義即將實做的函式">
定義即將實做的函式(圖片來源: <a href="https://medium.com/@meowent/python%E9%82%8F%E8%BC%AF%E5%B0%81%E8%A3%9D-%E5%AE%A2%E8%A3%BD%E7%89%B9%E5%AE%9A%E7%A8%8B%E5%BC%8F%E9%82%8F%E8%BC%AF%E5%B0%81%E8%A3%9D-3ed9ad0d098c">Wen Chang|Medium</a>)
</p>
#### 測驗與練習
1. **Python 擁有眾多函式提供給開發者使用,但若沒有自己想要的函式,可以根據自己要求客製化函式使用,稱作「自定義函式」,而自定義函式有一個很重要的關鍵字,請問為何?**
- [ ] `sorted`
- [ ] `sum()`
- [x] `def`
### 9-2|在 function 內直接輸出
課程這邊依照是否有回傳值分開講解,這一個章節會先教**在函式內直接輸出**的方法:
```python=
def checknumpr(x):
if(x%2==0):
print("是偶數")
else:
print("不是偶數")
checknumpr(5)
```
結果:
```bash=
不是偶數
```
<p class="illustration">
<img src="https://cdn-beta.hiskio.com/codefree/courses/mcf6hclyawk9gk2" alt="呼叫自定義函式">
呼叫自定義函式(圖片來源: <a href="https://codefree.hiskio.com/courses/28">Codefree - Python 進階篇</a>)
</p>
#### 測驗與練習
1. **自定義函式-判斷閏年**
請完成閏年判斷的自定義函式,根據閏年條件將程式完成,於函式內直接輸出是否為函式的結果。
- 條件1:能被 100 整除且能被 400 整除
- 條件2:不能被 100 整除且能被 4 整除
**答:**
```python=
def checkyear(year):
if((year%100==0 and year%400==0) or (year%100!=0 and year%4==0)):
print(year,"是閏年")
else:
print(year,"不是閏年")
#完成呼叫自定義函式,帶入參數2021
checkyear(2021)
```
### 9-3|function 結束後回傳資料值
承上CH 題目,一樣是判斷是否為偶數的程式,若使用函式的回傳值功能,程式將改寫為以下:
```python=
def checknum(x):
if(x%2==0):
return "是偶數"
else:
return "不是偶數"
answer=checknum(5)
print(answer)
```
結果:
```bash=
不是偶數
```
<p class="illustration">
<img src="https://cdn-beta.hiskio.com/codefree/courses/s24x8nlhj1p7z43" alt="呼叫自定義函式-回傳值">
呼叫自定義函式-回傳值(圖片來源: <a href="https://codefree.hiskio.com/courses/28">Codefree - Python 進階篇</a>)
</p>
#### 測驗與練習
1. **自定義函式-透過「回傳值」方法判斷閏年**
承上單元題目,請將閏年自定義函式改為回傳值(return)方式。
**答:**
```python=
def rCheckyear(year):
if((year%100==0 and year%400==0) or (year%100!=0 and year%4==0)):
return("是閏年")
else:
return("不是閏年")
year=2021
print(year,rCheckyear(year))
```
### 9-4|全域變數與區域變數
呼叫自定義函式時,需要注意變數的擺放位置,擺放位置會影響變數的作用域。若變數擺於函式的外面,則代表為**全域變數**;反之,則代表為**區域變數**。
全域變數運用的範圍需特別注意,它在函式內可被讀取,但若需要做其他的運算,則需將其在函式中命定 `global`;若沒有命定,則程式無法進行運算並且會拋出錯誤:
```python=
a=5
def countsum(x):
global a #將a定為全域變數
a+=x
return a
print("呼叫 countsum 函式之前的 a:",a)
print("呼叫 countsum 函式之後的 a:",countsum(3))
```
結果:
```bash=
呼叫 countsum 函式之前的 a: 5
呼叫 countsum 函式之後的 a: 8
```
#### 測驗與練習
1. **在程式當中的設定在自定義函式以外就稱作全域變數,若需要在自定義函式內使用全域變數做運算,則需要多執行什麼動作?**
- [ ] 將變數放在函數外
- [x] 在自定義函式中宣告「global」
- [ ] 電腦自己會知道哪些是全域變數
## CH 10|物件導向程式概念
### 10-1|什麼是物件?
物件導向程式設計(Object-oriented programming,OOP)有三大特色:**封裝(IEncapsulation)**、**繼承(Inheritance)**、**多型(Polymorphism)**。其優點在於程式比較有架構且可重複使用。
舉例來說,現實生活當中的人、貓、狗、椅子、桌子...等都可以稱作物件。而將這些資料抽象化則成類別,這些類別是由**屬性(attributes)** 和 **方法(method)** 所構成組成,若當我們將類別實例化時,就成了物件。
<div class="blockquote-center">
<p>
類別就如同物件的設計藍圖,物件則依照設計藍圖設計出來的實體。
</p>
</div>
我們以貓為例子,在類別中我們會定義它的資料:
- **屬性(attributes)**:貓毛的顏色、尾巴的長短...等等
- **方法(method)**:會吃、會叫
#### 測驗與練習
1. **類別(Class)中又包含哪些組成?**
- [ ] 類別(class)和方法(method)
- [x] 屬性(attribute)和方法(method)
- [ ] 類別(class)和物件(object)
<br>
2. **關於物件導向程式設計特色,以下何者並非為特色?**
- [ ] 繼承
- [x] 屬性
- [ ] 封裝
- [ ] 多型
### 10-2|物件(Object)與類別(Class)之間關係與使用
在創立類別時,需在程式當中寫關鍵字 `class` 後,並在其後接上類別名稱。習慣上,類別的命名會採用**大駝峰式**命名法:
```python=
class Cat: #類別名字第一個字母為大寫
print("這是一隻貓") #直接輸出
blackcat = Cat()
```
結果:
```bash=
這是一隻貓
```
在將類別實例化時,會直接呼叫類別名稱,並其賦值給指定變數,這就成了一個物件。
#### 測驗與練習
1. **使用類別(Class)**
有一支程式已有類別 Dog ,請試著使用該類別。
```python=
class Dog:
print("這是狗")
```
**答:**
```python=
class Dog:
print("這是狗")
#呼叫類別
dog = Dog()
```
<br>
2. **在創造類別(Class)時需注意名字的第一個字要特別做什麼動作?**
- [x] 第一個字母需大寫
- [ ] 最後一個字母需小寫
- [ ] 第一個字母需小寫
雖然這是公認的命名規則,但實際上它只是屬於命名潛規則,即便用小寫也不會跳 error。問我怎麼知道?我剛剛去嘗試過了!
<p class="illustration">
<img src="https://i.imgur.com/YgG3VBE.png" alt="類別命名字首不為大寫">
類別命名字首不為大寫
</p>
### 10-3|class 與 method 的關係
在前面章節中有講解到,類別當中有包含屬性和方法,而 Python 中會使用 `__init__()` 來設定初始屬性資料。
```python=
class People:
#self是必須的參數、其他參數例如voice是自己設定的參數
def __init__(self, voice):
self.peoplevoice = voice
chinese=People("你好~")
print(chinese.peoplevoice) #讀取該實例的 peoplevoice 資料
```
結果:
```bash=
你好~
```
<br>
而方法的定義,則與前一節的 function 定義一樣:
```python=
class People:
def __init__(self, voice):
self.peoplevoice = voice
def nationality(self,local):
self.local=local
print(self.local)
chinese=People("你好!") #設定實例
print(chinese.peoplevoice)
chinese.nationality("Taiwan") #使用color方法
```
結果:
```bash=
你好!
Taiwan
```
#### 測驗與練習
1. **改寫範例程式以創造新的實例**
請根據提供的範例程式,創造新的實例變數 english,並說「Hello~」。
**答:**
```python=
class People:
def __init__(self, voice):
self.voice = voice
def speak(self):
return "Hello~"
english = People("你好!").speak()
print(english)
```
### 10-4|繼承
物件導向程式觀念之中,最常運用到的就是**繼承**關係。在繼承關係中,會出現**父類別**與**子類別**兩個角色,子類別會承自父類別的程式架構,子類別再根據自身需求與特性進行修改。
以下圖形來觀察繼承觀念:
<p class="illustration">
<img src="https://cdn-beta.hiskio.com/codefree/courses/btbrr4xtgwgf6as" alt="類別命名字首不為大寫">
串列中的索引值(圖片來源: <a href="https://codefree.hiskio.com/courses/28">Codefree - Python 進階篇</a>)
</p>
結果:
```bash=
001
艾咪
女性
```
#### 測驗與練習
1. **物件繼承**
請設計一支程式,設立一個子類別(Class)為 Cat 去繼承父類別 Animal 的內容,並在子類別中設立一個方法「tail」輸出「有尾巴」。
**答:**
```python=
class Animal():
def __init__(self,voice):
self.voice=voice
print(self.voice)
class Cat(Animal):
def tail(self):
print("有尾巴")
tomcat=Cat("喵~")
tomcat.tail()
```
## 課程內容
1. [Codefree - Python 基礎篇](https://codefree.hiskio.com/courses/27)
2. [Codefree - Python 進階篇](https://codefree.hiskio.com/courses/28)
## 更新紀錄
:::spoiler 最後更新日期:2022-07-05
- 2022-07-05 發布
- 2022-07-05 完稿
- 2022-06-29 起稿
:::
<br><br>
> **本文作者**: 辛西亞.Cynthia
> **本文連結**: [辛西亞的技能樹](https://cynthiaCH uang.github.io/Hiskio-Codefree-Python/) / [hackmd 版本](https://hackmd.io/@CynthiaCH uang/Hiskio-Codefree-Python)
> **版權聲明**: 部落格中所有文章,均採用 [姓名標示-非商業性-相同方式分享 4.0 國際](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en) (CC BY-NC-SA 4.0) 許可協議。轉載請標明作者、連結與出處!