owned this note
owned this note
Published
Linked with GitHub
Python 基礎(1)
===
## Python簡介
Python 這一套功能強大、直譯式並且物件導向的程式語言,以強調對程式語言的語句易讀、易懂、易學及加快程式開發的時效,有許多程式設計者為Python提供了許多自行開發的library(函式庫),可以負荷支持平常大部份的應用,使得現今Python發展迅速及使用廣泛,相關資源也相當豐富。
## 安裝 Python 執行環境
### Windows
先至 Python 官網的下載頁面 https://www.python.org/downloads/ 下載 Python 安裝程式。由於之後要使用的網頁開發框架 Django 2 必須依存 Python 3,因此下載時請選擇 Python 3 以上的版本。

在執行安裝程式時,在第一個畫面上請勾選「Add Python 3.x to Path」,讓安裝程式自動設定 PATH 環境變數,這樣之後需在命令提示字元底下以指令的方式執行 Python 腳本程式時,系統才找得到相關的程式與資源。

Python 程式安裝後,我們先使用內附的 IDLE 直譯器來練習 Python 的基礎。先開啟Python的IDLE (Python GUI),然後按"File" -> "New File"。


這就是一個Python的編輯器,可以打好程式碼之後按"Run"->"Run Module",結果會呈現在交談式介面裡。

## 輸入與輸出
### 輸出
使用 `print` 最簡單的方法就是直接在 `print` 後面加上數字、文字、列表等,比如:
```python=
print(123)
print('abc')
x = 10
print(x)
d = [1,2,3]
print(d)
print(d[0])
```
`print()` 有兩個關鍵字參數:
1. `end`:輸出的結尾字元,預設為換行,可用空白、逗號或者空字串來取代換行。
2. `sep`:`print()` 可以同時傳入 N 個參數,`print()` 會以空白字元串起來後再輸出
```python=
print('香蕉', '蘋果', '鳳梨', sep=', ')
# 香蕉, 蘋果, 鳳梨
````
### 輸入
使用 `input` 輸入資料。
```python=
name = input('請問您的大名::\n') # 換行輸入
print('您好!' + name)
name = input('請問您的大名:: ')# 同一行輸入
print('您好!' + name)
```
## 常用的資料型別
### 數字(Number)
```python=
num1 = 5
num2 = 2
num3 = num1 + num2
```
#### 常用數學運算符號
- 加法 `+`
``` python
3 + 5
```
- 減法 `-`
``` python
3 - 5
```
- 乘法 `*`
``` python
3 * 5
```
- 除法 `/`
``` python
5 / 3
```
=> 結果為 `1.6666666666666667`
- 整數除法 '//'
``` python
5 // 3
```
=> 結果為 `1`
- 取餘數 '%'
``` python
5 % 3
```
=> 結果為 `2`
- 次方 '**'
``` python
2*8
```
=> 結果為 `256`
#### 其他
- 取亂數
使用方式:
``` python=
import random
random.randint(起點, 終點)
```
- 要先引用 `random` 套件
- `random` 套件中的 `randint` 是用來取某個範圍的整數亂數,包含起點,但不包含終點
例:
``` python=
import random
secret = random.randint(1000, 10000)
```
這樣會從 1000 ~ 9999 中隨機取一個 4 位數的整數亂數
### 字串(String)
字串用單引號 `'` 或雙引號 `"` 將字串內容前後包夾即可,只要同一組字串表示式的前後使用的引號一致即可;如果字串內容包含多行文字,則使用 3 對單引號或雙引號將完整字串包夾,例:
``` python=
myname = 'Dino Wei'
schoolname = "天真高中"
taiwan_metro_cities = """臺北
新北
桃園
臺中
臺南
高雄"""
```
#### 常用的字串操作
- 串接 `+`
``` python
str = schoolname + myname
```
- `str` 的內容會變為 `'天真高中Dino Wei'`
- 重複 `*`
``` python
divline = '----' * 10
```
`divline` 的內容會變為 `'----------------------------------------'`,也就是 `'----'` 重複 `10` 次的結果
- 取得某個位置的字元 `[位置]`
``` python
str = schoolname[2]
```
- `str` 的內容會變為 `'高'`
**注意:** 位置的編號從 `0` 號起算,第一個字元的編號是 `0`,所以位置編號 `2` 的符號實際上是第 `3` 個符號
- 若位置編號為負值,表示由尾端倒數,`-1` 表示字串中最後一個字元的位置,`-2` 表示倒數第 2 個字元的位置
``` python
str = schoolname[-1]
```
`str` 的內容會變為 `'中'`
- 取得子字串 `[起點:終點]`
``` python
str = schoolname[1: 3]
```
- `str` 的內容會變為 `'真高'`
- 包含起點,但是排除終點
- 若省略起點,則預設起點值為 `0`,例:`schoolname[:3]` 會取到 `'天真高'`
- 若省略終點,則預設終點值為字串終結,例:`schoolname[2:]` 會取到 `'高中'`
- 若起點終點指定的值為負值表示改由尾端倒數,例:`schoolname[-3:-1]` 則會取到 `'真高'`
- 取得字串長度: 內建函式 `len()`
``` python
strn = len(taiwan_metro_cities)
```
變數 `strn` 的結果為 `17`,其中有中文字 `12` 個,再加上 `5` 個換行符號。
### 布林值(Boolean)
`True` 或 `False`。注意在Python中布林值首字是大寫。
### 列表(List)
List 是 Python 中最基本的資料結構,用來表示一群資料的集合。列表用方括號 `[]` 將這群資料包含在其中,每筆紀錄間以逗號 `,` 隔開。
Python 列表中的每個元素的資料型態不必都相同。
``` python=
arbl = ['physics', '中文', 1997, 2018, [2, 3], 3.14159265358]
nums = [2, 1, 5, 8, 9, 6, 2, 5, 1, 3, 7]
letters = ["a", "b", "hello", "Google"]
```
List 中每一筆紀錄稱為元素,每個元素在列表中都被分配到一個數字素引值,用來表示該元素在列表中的位置。索引值的編號從 `0` 起算,第一個元素的索引值為 `0`,第二個元素的索引值為 `1`,依此類推。
若索引值為負值,表示由尾端倒數。`-1` 表示最後一個元素的索引值,`-2` 代表倒數第 2 個元素的索引值 ... 餘類推。
#### 列表常用的操作
- 存取列表中的元素 `[位置]` 或 `[起點: 終點]`
``` python=
arbl = ['physics', '中文', 1997, 2018, [2, 3], 3.14159265358]
nums = [2, 1, 5, 8, 9, 6, 2, 5, 1, 3, 7]
print("arbl[0]: ", arbl[0])
print("nums[1:5]: ", nums[1:5])
```
結果會輸出:
```
arbl[0]: physics
nums[1:5]: [1, 5, 8, 9]
```
指定位置或起點終點時,也可以與字串一樣,使用負值來表示由列表尾端倒數的位置,`-1` 表示最後一項,`-2` 表示倒數第二個 ...。
例:
``` python=
print("arbl[-3]:", arbl[-3])
print("nums[-3:]", nums[-3:])
```
會印出:
```
arbl[-3]: 2018
nums[-3:] [1, 3, 7]
```
要注意的是,若指定的位置超出列表的範圍,會引發 `IndexError` 執行階段錯誤,例:
``` python=
print(arbl[10])
```
目前 `arbl` 列表中只有 6 筆資料,編號為 `0` 至 `5` 號,因此欲取得編號 `10` 號的內容會引發錯誤:
```
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
```
- 新增至尾端 `.append()`
``` python=
list = [] # 空列表
list.append('Microsoft')
list.append('Google')
list.append('Apple')
print(list)
```
結果為
```
['Microsoft', 'Google', 'Apple']
```
- 取得目前列表內元素個數 `len()`
``` python
size = len(list)
```
- 刪除列表指定位置元素 `del`
``` python=
list = ['Apple', 'Google', 'Microsoft', 'Facebook']
print(list)
del list[2]
print(list)
```
結果為
```
['Apple', 'Google', 'Microsoft', 'Facebook']
['Apple', 'Google', 'Facebook']
```
- 測試列表中是否存在某元素 `in`
``` python=
nums = [1, 6, 4, 2, 8, 4, 2, 9, 0, 7, 7, 3, 7, 2, 1]
a = 100 in nums
print(a)
```
結果為 `False`
- 刪除指定元素值 `.remove()`
``` python=
nums = [1, 6, 4, 2, 8, 4, 2, 9, 0, 7, 7, 3, 7, 2, 1]
print(nums)
nums.remove(7)
print(nums)
```
**注意:** `remove()` 只會移除掉第 1 個符合指定元素值的元素,如果指定元素值不存在,則會引發執行例外
- 組合其他列表 `+`
``` python=
a = [1, 3, 5, 7, 9]
b = [2, 4, 6, 8, 10]
c = a + b
print (c)
```
結果為
```
[1, 3, 5, 7, 9, 2, 4, 6, 8, 10]
```
### 值組 (Tuple)
值組跟列表很像,但它們最大的差異點是,列表的內容是可以更動的,但是值組不行。在建立值組的時候以一對小括號 `()` 涵括要包含的值,值與值之間以逗號 `,` 隔開:
``` python=
tuple_a = ('Taiwan', 'Taipei', 10462)
```
或者省略小括號也可以:
``` python=
tuple_b = 'Taiwan', 'Taipei', 10462
```
值組內的每項資料也會自動由 `0` 開始依序編號。值組一但建立之後,就無法變更該值組內索引值與其對應值的關係,例:
``` python=
tuple_a[1] = '臺中'
```
想將 `tuple_a` 中的第 `2` 項資料修改為 `'臺中'`,會引發 `TypeError` 錯誤:
```
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
```
列表允許的操作當中,只要不涉及資料的變更,也可以套用在值組上:
``` python=
zipCode = tuple_b[2] # 取得 10462
cityZip = tuple_a[1:] # 取得 ('Taipei', 10462)
count = len(tuple_a) # 取得 3
hasTaiwan = 'Taiwan' in tuple_a # True, 因為 tuple_a 裡有包含 'Taiwan'
```
另外,在多數的程式語言中,要交換 2 個變數的內容時,通常都要透過第 3 個變數先暫存其中 1 的原始值:
``` python=
a = 3
b = 5
c = a # 暫存 a 的原值
a = b # a 已暫存,可以用 b 的值蓋掉了
b = c # 透過 c 暫存的值,將 a 的原值指定給 b
```
在 python 中有另一種方便的寫法:
``` python=
a, b = b, a # 等同於 (a, b) = (b, a)
```
### 字典(Dictionary)
字典也是另一種常用的資料結構,跟列表相似的是,它也是用來表示某些資料的集合,但不同點在於,列表的索引是系統自動編號的,但是字典則是由使用者自行指定,而且其索引鍵不必為數值,也可以是字串或其他類型的資料。
要建立字典,可使用花括號 `{}` 將紀錄以 `鍵值:內容` 的型式包起來,紀錄與紀錄之間以逗號 `,` 隔開。
```python=
scores = {'Dino': 90, 'Rita': 95, 'John': 87, 'Tom': 79, 'Mary': 92, 'George': 66}
# 建立字典
students = {10730029: '10205', 10730001: '10101'}
```
#### 字典常用操作
- 取得字典中的資料筆數 `len()`
內建函式 `len()` 可取得字典內已登錄的資料的數量,例:
``` python=
print(len(scores))
```
會印出 `6`
- 取得字典中某鍵值的對應值 `[]`
``` python=
print(scores['Dino'])
```
印出 `scores` 字典中, `'Dino'` 所對應到的對應值,應該會印出 `70`。
若是該鍵值在字典中不存在,則會觸發執行期間的錯誤,例:
``` python=
print(scores['Jack'])
```
會發生錯誤,並顯示錯誤訊息:
```
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'Jack'
```
這個錯誤的意思是說,指定的鍵值有誤,表示字典中尚未有 `'Jack'` 這筆紀錄存在。
- 新增/更新一筆紀錄 `=`
``` python=
scores['Micky'] = 89 # 新增 'Micky' 的值為 89
scores['George'] = 71 # 將 'George' 對應到的值修改為 71
```
需搭配鍵值使用。若指定的鍵值尚未登錄在字典中,則會直接新增一筆紀錄;反之,若鍵值已存在,則修改其對應值。
- 刪除一筆記錄 `del`
``` python=
del students[10730001];
```
在 `del` 關鍵字後接上欲刪除的字典及鍵值即可。要注意的是,如果該鍵值在字典內不存在的話,同樣也會引發 `KeyError` 錯誤:
``` python=
del scores['Justin'];
```
```
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'Justin'
```
- 測試某鍵值是否已存在字典內 `in`
通常會搭配條件判斷 `if` 來使用,例:
``` python=
if myKey in scores:
del scores[myKey]
```
檢查變數 `myKey` 的內容是否為 `scores` 字典中已登錄的鍵值,若是,則刪除該筆記錄。
- 取得所有鍵值的列表 `.keys()`
``` python=
myKeys = scores.keys() # 取得 scores 字典中所有鍵值的列表
print (myKeys)
```
會印出:
```
dict_keys(['Dino', 'Rita', 'John', 'Tom', 'Mary', 'George'])
```
- 取得所有對應值的列表 `.values()`
若想取得字典中所有對應值的列表,則改用 `.values()` 方法:
``` python=
myValues = scores.values() # 取得 scores 字典中所有對應值的列表
print(myValues)
```
會印出:
```
dict_values([90, 95, 87, 79, 92, 66])
```
- 取得所有鍵值與對應值紀錄的列表 `.items()`
字典中每一筆紀錄都包含了鍵值與對應值,要透過 `.items()` 取得每筆紀錄的話,回傳的列表中,每筆紀錄都是以 `(鍵值, 對應值)` 這樣的型式呈現。
``` python=
recs = scores.items()
print(recs)
```
會印出
```
dict_items([('Dino', 90), ('Rita', 95), ('John', 87), ('Tom', 79), ('Mary', 92), ('George', 66)])
```
### 集合(Set)
集合裡面會包含不重複的元素值,如果不需要鍵值的話,只是單純要紀錄某個值出現過了沒有,就適合使用集合來處理。
```python=
s = set()
s.add(3) # { 3 }
s.add(6) # { 3, 6 }
s.add(6) # { 3, 6 }
len(s) # 2
```
要定義一個空集合的話,可以使用 `set()`:
``` python=
s1 = set()
```
若要從一個現成的字串、列表、字典、值組來定義集合的話,可以將資料來源放在 `set()` 的小括號內:
``` python=
list_a = [1, 3, 5]
tuple_b = (1, 2, 1, 3, 4, 3)
dic_c = {'A': 65, 'C': 67, 'b': 98}
str_d = "hello"
sa = set(list_a) # {1, 3, 5}
sb = set(tuple_b) # {1, 2, 3, 4} 原本重複的 1, 3 在集合中僅出現一次
sc = set(dic_c) # {'b', 'C', 'A'} 僅包含字典的鍵值
sd = set(str_d) # {'o', 'h', 'e', 'l'}
se = set([2, 3, 5, 7, 11]) # {2, 3, 5, 7, 11}
```
甚至也可以用花括號 `{}` 來定義集合,將集合內的元素值直接寫在花號號內,元素間以逗號 `,` 隔開:
``` python=
sf = {1, 1, 2, 3, 5, 8, 13} # {1, 2, 3, 5, 8, 13} 重複的 1 自動被移除了
```
::: warning
:warning: **以花括號 `{}` 來定義集合的注意事項**
`{}` 可以用來定義字典,也可以用來定義集合,差別在於列舉內容時,字典需以 `鍵值: 對應值` 方式來指定每一組對應關係,而集合因為不包含鍵值,直接列出值就可以了:
``` python=
dic_a = {1:'one', 'two':2} # 定義字典
set_b = {'one', 2} # 定義集合
```
如果要定義一個空集合的話,只能使用 `set()` 來定義,因為花括號內沒有內容,會被 Python 解釋為一個空的字典。
``` python
empty_set = set() # 空集合
empty_dic = {} # 空的字典
```
:::
#### 集合的常用操作
為了方便說明,先定義以下 3 個集合:
``` python=
sa = {1, 2, 3, 4, 5}
sb = {2, 4, 6, 8, 10}
sc = {1, 3, 5, 7, 9}
```
- 取得集合內的元素個素: `len()`
``` python=
elements = len(sa) # elements 的值為 5
```
- 聯集: `.union()` 或 `|`
``` python=
su1 = sa.union(sb) # {1, 2, 3, 4, 5, 6, 8, 10}
su2 = sb | sc # {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
```
產生一個新的集合,內容為兩個集合的聯集。聯集的元素包含兩個集合中的所有元素:

- 交集: `.intersection()` 或 `&`
``` python=
si1 = sa.intersection(sb) # {2, 4}
si2 = sb & sc # set()
```
產生一個新集合,內容為兩個集合的交集。要同時出現在兩個集合中才會被挑出來:

- 差集: `.difference()` 或 `-`
``` python=
sd1 = sa.difference(sb) # {1, 3, 5}
sd2 = sc - sa # {7, 9}
```
產生一個新的集合,內容為出現在第一個集合但不出現在第二個集合的所有元素:

- 對稱差: `symmetric_difference()` 或 `^`
``` python=
ssd1 = sa.symmetric_difference(sb) # {1, 3, 5, 6, 8, 10}
ssd2 = sb ^ sa # {1, 3, 5, 6, 8, 10}
```
產生一個新的集合,內容為兩個集合中,僅出現在其中一個集合的所有元素,也就是兩個集合的聯集扣掉它們的交集的結果:

- 測試是否與另一個集合不相交(沒有共同元素): `.isdisjoint()`
如果兩個集合彼此間沒有共同的元素的話,稱為不相交(disjoint),換句話說,它們的交集會是空集合。
``` python=
print(sa.isdisjoint(sb)) # False
print(sb.isdisjoint(sc)) # True
```
- 測試兩個集合是否相等: `==`
兩個集合相等的定義為兩個集合中包含的元素內容要完全相等,也就是說所有在集合 A 中包含的元素,要出現在集合 B 中;反過來說,所有包含在集合 B 中的元素也得出現在集合 A 裡。
``` python=
s1 = {1, 3, 5}
s2 = {5, 1, 3}
print (s1 == s2) # True
```
- 測試是否為另一個集合的子集合: `.issubset()` 或 `<=`
若集合 A 中包含的所有元素都會出現在集合 B 中,此時稱集合 A 為集合 B 的子集合(subset)。
``` python=
s1 = {1, 2, 4, 8}
s2 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
print(s1.issubset(s2)) # True
print(s1 <= s2) # True
```
在此定義之下,任意一個集合都會是該集合自身的子集合:
``` python=
print(s1 <= s1) # True
```
- 測試是否為另一個集合的真子集合(proper subset): `<`
若集合 A 為集合 B 的子集合,且集合 A 與集合 B 不完全相同,亦即集合 B 中包含了某些集合 A 中沒有的元素,此時稱集合 A 為集合 B 的真子集合(proper subset)。
``` python=
s1 = {1, 2, 3, 4, 5}
s2 = {5, 2, 4, 1, 3}
s3 = {3, 1}
print(s2 <= s1) # True
print(s2 < s1) # False,因為 S2 與 S1 的內容相同
print(s3 < s2) # True
```
- 測試是否為另一個集合的超集合: `.issuperset()` 或 `>=`
超集合(superset)的定義與子集合剛好相反。若集合 A 為集合 B 的子集合,則集合 B 就稱為集合 A 的超集合。
- 測試是否為另一個集合的真超集合(proper superset): `>`
- 聯集更新: `.update()` 或 `|=`
上面提到的 `.union()`、`.intersection()`、`.difference()` 以及 `.symmetric_difference()` 都會產生一個新的結果集合,不會變更原集合的內容。若想以聯集、交集、差集、對稱差的結果替換掉原本的集合的話,可以用接下來介紹的幾個方法。
``` python=
s1 = {1, 2, 3, 4, 5}
s2 = {2, 4, 6, 8, 10}
s1.update(s2) # 或 s1 |= s2
print(s1) # {1, 2, 3, 4, 5, 6, 8, 10}
```
- 交集更新: `.intersection_update()` 或 `&=`
``` python=
s1 = {1, 2, 3, 4, 5}
s2 = {2, 4, 6, 8, 10}
s1 &= s2 # 或 s1.intersection_update(s2)
print(s1) # {2, 4}
```
- 差集更新: `.difference_update()` 或 `-=`
``` python=
s1 = {1, 2, 3, 4, 5}
s2 = {2, 4, 6, 8, 10}
s1.difference_update(s2) # 或 s1 -= s2
print(s1) # {1, 3, 5}
```
- 對稱差更新: `.symmetric_difference_update()` 或 `^=`
``` python=
s1 = {1, 2, 3, 4, 5}
s2 = {2, 4, 6, 8, 10}
s1 ^= s2 # 或 s1.symmetric_difference_update(s2)
print(s1) # {1, 3, 5, 6, 8, 10}
```
- 新增一個元素: `.add()`
``` python=
s1 = {1, 2, 3, 4, 5}
s1.add('a')
print(s1) # {1, 2, 3, 4, 5, 'a'}
```
- 刪除一個元素: `.remove()` 或 `.discard()`
`.remove()` 與 `.discard()` 方法都是用來將元素從集合中移除,差別在於 `.remove()` 方法遇到指定的元素不存在時,會引發 `KeyError` 錯誤,而 `.discard()` 不會。
``` python=
s1 = {1, 2, 3, 4, 5}
s1.remove(3)
print(s1) # {1, 2, 4, 5}
s1.discard(4)
print(s1) # {1, 2, 5}
s1.discard(3)
s1.remove(3) # 這行會發生 KeyError 錯誤!!!!因為 3 不存在
```
- 取出一個元素: `.pop()`
集合物件的 `.pop()` 方法會從集合中取出一個元素回傳。
``` python()
s1 = {1, 2, 3, 4, 5}
n = s1.pop() # n 的值可能為 s1 中的任一個元素
print(s1)
```
::: warning
:warning: 用 `.pop()` 方法取出元素時沒有規定會依照特定的順序,請不要自行假設它會依序由小到大取值,這是其中一種可能,但非絕對。
:::
另外,若集合本來就空了,此時使用 `.pop()` 方法也會引發 `KeyError` 錯誤:
```
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'pop from an empty set'
```
- 將集合清空: `.clear()`
``` python=
s1 = {1, 3, 5, 2, 4, 6}
print(s1) # {1, 2, 3, 4, 5, 6}
s1.clear()
print(s1) # set()
```
## 流程控制
流程控制可以根據當下的狀況是否滿足某些條件,來進行不同的處置。而在描述條件的時候,通常是在比較兩樣事物之間的關係,例:
- **如果成績不及格的話**:比較的是 **成績** 與 **60** 分之間的關係。
- **如果下雨的話**:比較的是 **天氣狀態** 與 **下雨** 這個現象的關係。
- **如果 n 是偶數的話**:比較的是 **n 除以 2 的餘數** 以及 **0** 之間的關係。
_註:有時可能要經過轉換或計算之後才進行比較_
### 關係運算子
關係運算子跟數學的四則運算子的概念相同,只是它的運算結果只有 `True` 或 `False` 兩種可能,用來代表關係成立(`True`)或不成立(`False`)。
|關係運算子|範例|說明|
|-|-|-|
| `>` | `A > B` | 若 `A` 比 `B` 大,則結果為 `True`,否則為 `False` |
| `>=` | `A >= B` | 若 `A` 大於或等於 `B` 則為 `True`,否則為 `False` |
| `<` | `A < B` | 若 `A` 比 `B` 小,則結果為 `True`,否則為 `False` |
| `<=` | `A <= B` | 若 `A` 小於或等於 `B` 則為 `True`,否則為 `False` |
| `==` | `A == B` | 若 `A` 與 `B` 等值則為 `True`,否則為 `False` |
| `!=` | `A != B` | 若 `A` 與 `B` 不相等,則結果為 `True`,否則為 `False` |
### 邏輯運算子
除了關係運算子之外,在描述比較複雜的狀況的時候,可能會需要同時需要用到幾個簡單條件來組合出完整的複合式條件,這時候會需要用到邏輯運算子。
|邏輯<br/>運算子|範例|說明|
|-|-|-|
| `and` | `n >= 60 and n < 70` | `and` 前後條件皆為 `True`,結果才為 `True`。<br/>判斷 `n` 的值是否介於 `60`(包含) 與 `70` 之間 |
| `or` | `n < 0 or n > 100` | `or` 前後條件至少有一個為 `True`,結果即為 `True`。<br/>判斷 `n` 的值是否小於 `0` 或超過 `100` |
| `not` | `not n < 60` | 將 `not` 後面的 `True` 改為 `False`,`False` 改為 `True`。<br/>判斷 `n` 的值是否沒有小於 `60`。|
### 條件判斷 if
#### 單選/條件成立才執行
語法:
``` python
if 條件判斷式:
動作1
動作2
動作3
#...
不被 if 控制的動作
```
- 條件判斷式之後的冒號 `:` 不要漏掉了。
- Python 是以程式碼的「**縮排**」來決定從屬或控制關係,上方的例子中,動作1, 2, 3 都是條件判斷式成立的時候才會被執行到,所以前面都要縮排。
- 縮排可以用空格(Space),也可以用定位鍵(Tab)。同一層的縮排務必使用一致的縮排方式,否則會引發 `IndentationError` 錯誤。
例:如果變數 `score` 已取得了某個學生的成績,若不及格,則將不及格人數+1,並在成績前加印 `*`;若成績及格的話,只要印成績就好:
``` python=
if score < 60:
failed += 1 # 不及格人數 +1
print('*', end='') # 在分數前面加印 *
print(score) # 印出成績
```
#### 二選一
如果要處理條件成立與不成立分別進行不同的動作的話,可以採用第二種形式 `if/else`,語法如下:
``` python
if 條件判斷式:
成立動作1
成立動作2
# ...
else:
不成立動作1
不成立動作2
# ...
非 if 控制動作 ...
```
::: warning
:warning: **`else` 後面不要忘了加冒號 `:`**
:::
若條件判斷式的運算結果為 `True`,就執行 `if` 到 `else:` 之間的動作;反之若條件判斷的結果為 `False`,就執行 `else:` 底下的動作。
例如,若要計算及格與不及格的人數,在每次取得一筆成績之後,就用以下的判斷式來更新及格人數(`passed`)或不及格人數(`failed`):
``` python=
if score >= 60:
passed += 1 # 及格人數 +1
else:
failed += 1 # 不及格人數 +1
total += 1 # 總人數 +1
```
#### 多選一
如果要處理的是多選一的狀況,可以採用 `if/elif.../else` 結構,語法如下:
``` python
if 條件判斷式1:
# 區塊1
elif 條件判斷式2:
# 區塊2
elif 條件判斷式3:
# 區塊3
else:
# 以上均不符合執行這裡
```
會由上到下依序評估條件判斷式,若前一個條件無法成立,才會評估下一個條件,一直到評估的條件判斷式結果為 `True` 就執行該條件下的區塊內容;若所有匡列的條件判斷式都無法測試成功時,則執行 `else:` 之下的動作。
所以若要執行到 `區塊2` 的內容的話,一定是不滿足條件判斷式1,但條件判斷式2的結果要為 `True` 才可以。同理,若要執行 `區塊3` 內的動作的話,一定是前面兩個判斷式的估評結果皆為 `False` 而條件判斷式3的結果為 `True` 才會發生。
以成績處理為例,若要將成績 `score` 轉為 `A` (90分以上)、`B` (80 - 89分)、`C` (70 - 79分)、`D` (60 - 69分)、`E` (未滿 60 分):
``` python=
if score >= 90: # score >= 90
label = 'A'
elif score >= 80: # 80 <= score < 90
label = 'B'
elif score >= 70: # 70 <= score < 80
label = 'C'
elif score >= 60: # 60 <= score < 70
label = 'D'
else: # score < 60
label = 'E'
```
::: warning
:warning: **注意:每個條件判斷式之後,以及 `else` 後面都要加上冒號 `:`**
:::
因為是依序評估條件判斷式,所以會進行++第 3 行++的 `score >= 80` 這個條件式的估評時,隱含了此時一定是不滿足++第 1 行++的 `score >= 90` 這個條件,換句話說,要進行++第 3 行++的條件估評時,此時一定滿足 `score < 90` 的情況。雖然字面上在++第 3 行++只寫了 `score >= 80` 這個條件,但實際上這行的效果等同於在判斷 `score < 90 and score >= 80`。
### 條件式迴圈 while
`if` 結構只會進行單次判斷,如果希望在特定條件下反覆執行某些動作的話,可以使用條件式迴圈 `while`,語法如下:
``` python
while 條件判斷式:
動作1
動作2
# ...
非 while 控制的動作
```
- 注意條件判斷式後面的冒號 `:` 不要漏掉了。
- 當條件判斷式成立的情況下會執行迴圈內容,然後再回頭重新評估條件判斷式決定是否要執行迴圈內容,如此重覆直到條件判斷式的運算結果為 False 為止。
- 要注意在迴圈內容中要有機會可以修改到條件判斷式的評斷依據,否則會造成無窮迴圈。
例如數學領域有一個尚未證明的問題如下:給定一個整數 `n`,若 `n` 是奇數,則將它變為它的 `3` 倍再加 `1`;若它是偶數,則將它變為它的一半。人們發現,目前已知的所有正整數,依上述原則反覆操作,最後都會收斂到 `1`。舉個例子來說,一開始給定 `n` 為 `13`,依規則操作,`n` 的值變化的歷程為:
```
13 -> 40 -> 20 -> 10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1
```
若 `n` 一開始為 `12`,則變化過程為:
```
12 -> 6 -> 3 -> 10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1
```
給定一個正整數 `n`,要模擬上面印出 `n` 的值變化的過程的話,程式碼大概如下:
``` python=
# n 為大於 0 的整數
while n > 1:
print(n, "-> ", end='') # 在 n 不為 1 的情況下,都要印出 n 值以及 ->
if n % 2 == 1: # n 是奇數
n = n*3 + 1
else: # n 不是奇數(n 是偶數)
n = n//2 # 整數除法
print(n)
```
### 迭代式迴圈 for…in
語法:
``` python
for 變數 in range(起點, 終點, 遞增值):
動作1
動作2
# ...
```
- 以 `變數` 來接收每一回合迭代的內容,可自行命名
- `range()` 是 Python 內鍵的函式,用來產生在指定範圍內的數列,它接受 3 個參數:
1. `起點` 欲產生的數列的起點
2. `終點` 是數列的終點,不包含在被產生的數列之內
3. `遞增值` 是每一回合變數取到的值加上多少才會成為下一回合的數字。這個參數可省略,預設值為 `1`
例:列出 1 到 100 間被7除餘 3 的數
``` python=
for n in range(1, 100):
if n % 7 == 3:
print(n)
```
這個問題很簡單,馬上就看出規律,所以也可以透過遞增值拿掉迴圈內的 `if` 判斷:
``` python=
for n in range(3, 100, 7):
print(n)
```
如果要由大到小產生遞減的數列,要將第三個參數改為負值,例如要產生 10 到 1 的數列:
``` python=
for n in range(10, 0, -1):
print(n)
```
除了在產生的數列進行迭代之外,迭代的對象也可以是**列表(list)**、**值組(tuple)**、**字典(dict)**、**集合(set)** 等等這類資料容器(Container),語法如下:
``` python
for 變數 in 容器:
動作1
動作2
# ...
```
例如,假設 `groups` 內儲存的是分組的狀況,每組 3 個人,每一組成員的座號以值組的方式呈現:
``` python=
groups = [
(2, 8, 9), (1, 5, 11), (16, 17, 21), (3, 6, 13),
(4, 7, 12), (10, 14, 20), (15, 18, 19)
]
for grp in groups: # 每次取一組 tuple
for m in grp: # 從 tuple 中依次取出元素
print(m, end=' ') # 印出成員座號後不換行,改印一個空格
print('') # 印完一組之後才換行
```
執行結果如下:
```
2 8 9
1 5 11
16 17 21
3 6 13
4 7 12
10 14 20
15 18 19
```
但是要注意一點的是,當迭代的對象如果是一個字典的時候,每次迭代取得的是鍵值(Key),例:
``` python=
scores = {'Dino': 90, 'Rita': 95, 'John': 87, 'Tom': 79, 'Mary': 92, 'George': 66}
for s in scores:
print(s, end=' ')
```
只會會印出鍵值:
```
Dino Rita John Tom Mary George
```
如果需要處理鍵值的對應值,還需搭配字典的 `[]` 操作來取得對應值。例如要將前面範例中成績達 `90` 分的學生名字前標上 `*`:
``` python=
for s in scores:
if scores[s] >= 90:
print('*', s, sep='')
else:
print(' ', s, sep='')
```
執行結果如下:
```
*Dino
*Rita
John
Tom
*Mary
George
```
### 跳出迴圈 `break` 與 跳過一回合 `continue`
`while` 與 `for...in` 這兩種迴圈,若在執行的過程中發現已經完成任務了,可以在迴圈內透過 **`break`** 指令來跳離迴圈,一旦執行到 `break` 就會終止迴圈的執行,跳離到不受迴圈控制的第一行。例:
``` python=
for i in range(10):
if i % 3 == 2:
break
print(i)
print('End for')
```
執行結果:
```
0
1
End for
```
若僅是要跳過一個回合,則可在迴圈內使用 **`continue`**。當執行到 **`continue`** 時,會略過該回合尚未被執行到的敘述,直接進入下一回合:
``` python=
for i in range(10):
if i % 3 == 2:
continue
print(i)
print('End for')
```
執行結果:
```
0
1
3
4
6
7
9
End for
```
跳過所有被 3 除餘 2 的回合。
在 `while` 迴圈內使用 `continue` 時,要注意執行 `continue` 的時機點會不會造成迴圈條件無法被變更,導致無窮迴圈。例下面這段程式:
``` python=
i = 0
while i < 10:
if i % 3 == 2:
continue
print(i)
i += 1
print('End for')
```
- 印出 `0`, `1` 之後就陷入無窮迴圈了
要處理這個問題,只要在執行 `continue` 前也將迴圈條件內使用的變數 `i` 的值修正為下一回合的值就可以了:
``` python=
i = 0
while i < 10:
if i % 3 == 2:
i += 1
continue
print(i)
i += 1
print('End for')
```
### 函式
函式(function)是重複使用的程式區塊,有輸入與輸出。在 Python 中使用關鍵字 `def` 來定義函式,語法如下:
``` python
def 函式名(參數列表):
# 函式內容
# ...
return 傳回值
```
- **函式名** 可自行命名,建議取與該函式功能相關的名稱
- **參數列表** 是執行這個函式時,額外提供給函式的資訊。若函式都執行固定內容,可省略參數列表。若需要的參數超過 1 個以上,參數間以逗號 `,` 隔開
- **傳回值** 是用來回覆函式執行結果
舉例來說,假設在程式中好幾處需要使用到 2 個數的最大公因數,就可以考慮定義一個函式:
``` python=
def gcd(a, b):
# 使用輾轉相除法來求最大公因數
r = a % b
while r > 0: # 要一直進行到餘數為 0 為止
a = b
b = r
r = a % b
return b # 答案為最後一次的除數
```
定義完 `gcd()` 函式之後,接下來在任何需要求取最大公因素的地方,就可以直接呼叫 `gcd()` 函式:
``` python=
if gcd(123, 217) == 1:
print('123 與 217 互質')
```
呼叫函式時只要將需要的參數附在函式名稱後的小括號內即可,如上所示,透過 `gcd(123, 217)` 來呼叫 `gcd()` 函式,並將 `123` 與 `217` 當作參數傳遞給 `gcd()` 函式來執行。在函式內部執行的時候,參數 `a` 一開始取得的值就是 `123`,而 `b` 則為 `217`。