# Python - ch.02 資料型別、變數與運算子
[TOC]
## 2-1 Python 資料型別
### `(2-1-bool1.py)` 布林值
這三行程式碼都是在使用 `bool()` 函式將不同的資料轉換成布林值(`True` 或 `False`)。下面是加上詳細註解的版本:
```python!
# 將數值 1 轉為布林值。非零數字會被視為 True
print(bool(1)) # 輸出:True
# 將數值 0 轉為布林值。0 被視為 False
print(bool(0)) # 輸出:False
# 將空的 tuple(元組)轉為布林值。空容器(如空字串、空串列、空字典、空集合、空元組)都是 False
print(bool(())) # 輸出:False
```
#### ✅ 延伸說明:哪些東西在 `bool()` 中會被視為 False?
下列資料在轉成布林值時會是 `False`:
* 數值:`0`, `0.0`
* 空字串:`""`
* 空串列:`[]`
* 空元組:`()`
* 空字典:`{}`
* 空集合:`set()`
* 特殊值:`None`
其他情況幾乎都會是 `True`。
---
### `(2-1-int1.py)` 整數
這三行程式碼使用了 **Python** 的 `int()` 函式,來將不同型別或不同進位制的值轉換為十進位的整數。以下是**每行加上清楚中文註解的版本**:
```python!
# 將整數 100 傳入 int(),保持原樣,結果仍是整數 100
print(int(100)) # 輸出:100
# 將浮點數 3.14 傳入 int(),會「捨去小數部分」轉成整數
print(int(3.14)) # 輸出:3
# 將字串 '100' 視為二進位(base=2)轉為十進位整數
# '100' 在二進位中表示 1×2² + 0×2¹ + 0×2⁰ = 4
print(int('100', 2)) # 輸出:4
```
#### 🔍 補充說明:
| 表達式 | 說明 | 結果 |
| :--------------- | :---------------------------: | :---: |
| `int(100)` | 已是整數,直接輸出 | 100 |
| `int(3.14)` | 浮點數轉整數,**小數捨去** | 3 |
| `int('100', 2)` | 把 `'100'` 當成 **二進位** 的數字來轉換 | 4 |
---
### `(2-1-float1.py)` 浮點數
這三行程式碼是使用 `float()` 函式將不同的資料轉換成浮點數(帶小數點的數字)。以下是加上中文註解的版本:
```python!
# 將整數 1 轉換成浮點數,結果為 1.0
print(float(1)) # 輸出:1.0
# 將浮點數 3.14 傳入 float(),本身已是浮點數,輸出不變
print(float(3.14)) # 輸出:3.14
# 將字串 '3.1415' 轉換成浮點數
print(float('3.1415')) # 輸出:3.1415
```
#### 補充說明:
- `float()` 可以將整數或字串(格式正確的數字字串)轉為浮點數。
- 字串必須是有效的數字格式,否則會發生錯誤(例如 `float('abc')` 會報錯)。
---
### `(2-1-str1.py)` 字串
這段程式碼示範了 **Python** 字串不可變(immutable)的特性,這是很重要的觀念。以下是加上註解並說明錯誤原因:
```python!
# 建立字串 'Python' 並存入變數 s
s = str('Python')
# 嘗試將字串第一個字元改成 'Q'
# 這會導致錯誤,因為 Python 的字串是不可變的(immutable)
# 不能直接改變字串內部的單一字元
s[0] = 'Q' #字串不可更改,會出現錯誤
```
輸出結果:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[6], line 7
2 s = str('Python')
4 # 嘗試將字串第一個字元改成 'Q'
5 # 這會導致錯誤,因為 Python 的字串是不可變的(immutable)
6 # 不能直接改變字串內部的單一字元
----> 7 s[0] = 'Q'
TypeError: 'str' object does not support item assignment
#### 為什麼會錯?
* **Python** 的字串是不可變物件,無法透過索引直接修改某個字元。
* 你可以用建立新字串的方式來達成想要的結果。
#### 改寫範例:用新字串取代原本字串
```python!
# 利用字串切片和串接,改變第一個字元為 'Q'
s = 'Python'
s = 'Q' + s[1:]
print(s) # 輸出:Qython
```
這樣就能達到「修改字串中某個字元」的效果,實際上是建立一個新字串並指派回變數。
---
### `(2-1-type.py)` 使用type顯示資料型別
這段程式碼用來示範不同資料型態的變數宣告及其型別輸出,下面是加上註解的版本:
```python!
# 布林值 True,代表真
b = True
# 印出 b 的值及其資料型態 <class 'bool'>
print(b, type(b))
# 整數 20
num = 20
# 印出 num 的值及其資料型態 <class 'int'>
print(num, type(num))
# 浮點數 3.14
pi = 3.14
# 印出 pi 的值及其資料型態 <class 'float'>
print(pi, type(pi))
# 字串 "Hello"
s = "Hello"
# 印出 s 的值及其資料型態 <class 'str'>
print(s, type(s))
```
#### 執行結果範例:
True <class 'bool'>
20 <class 'int'>
3.14 <class 'float'>
Hello <class 'str'>
#### 補充說明:
- `type()` 函式會回傳變數的資料型態。
- **Python** 是動態型別語言,變數不用事先宣告型別,會根據賦值自動推斷。
- 常見基本資料型態有:`bool`、`int`、`float`、`str` 等。
---
## 2-2 變數
### `(2-2-1a-var1.py)` 印出變數 `a` 之前,變數 `a` 並未參考到任何物件,出現 `NameError` 表示變數 `a` 未定義
這行程式碼會出現錯誤,因為變數 `a` 尚未被定義。
```python!
print(a)
```
#### 🧯 錯誤訊息(範例):
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[8], line 1
----> 1 print(a)
NameError: name 'a' is not defined
#### 🔍 錯誤說明:
- **Python** 執行到 `print(a)` 時,會嘗試尋找名為 `a` 的變數。
- 如果之前沒有寫過 `a = ...,Python` 就會報出 `NameError`(名稱錯誤)。
#### ✅ 正確範例:
先定義 `a` 才能使用:
```python!
a = 10
print(a) # 輸出:10
```
---
### `(2-2-1b-var2.py)` 變數 a 經由「=」參考到不同的物件
```python!
# 將整數 1 指派給變數 a
a = 1
# 印出變數 a 的值與它的記憶體位址(透過 id() 函數取得)
print(a, id(a))
# 將字串 'Python' 指派給變數 a(此時 a 原本的值 1 被覆蓋)
a = 'Python'
# 再次印出 a 的值與它的記憶體位址,這時的 id 值會與之前不同
print(a, id(a))
```
#### ✅ 執行說明(範例輸出會依環境不同而異):
假設輸出如下:
1 140706127547120
Python 2411030893680
可以看到:
- 第一次 `a = 1`,`id(a)` 是某個位址(假設是記憶體中的整數物件 `1`)。
- 第二次 `a = 'Python'`,變數 `a` 被重新綁定到一個新的字串物件,記憶體位址也跟著變了。
#### 🔍 核心觀念:
- **Python** 中變數是「名稱」或「參考」,不是像 **C/C++** 那樣是「盒子」。
- 當你寫 `a = 1` 時,`a` 被綁定到整數物件 `1`。
- 當你寫 `a = 'Python'` 時,`a` 被綁定到字串物件 `'Python'`,與原本的 `1` 無關。
---
### `(2-2-1c-var3.py)` 變數 `y` 經由「=」參考到變數 `x` 所參考的物件,變數 `x` 與變數 `y` 參考到相同物件
這段程式碼展示了 **變數指派與記憶體位置(物件 ID)** 的概念,尤其在 **Python** 中變數是「參考」(reference)的語言。以下是加上中文註解與說明的版本:
```python!
# 將整數 1 指派給變數 x
x = 1
# 將變數 x 的值(也就是整數 1)指派給變數 y
# 注意:x 和 y 會指向同一個整數物件(1)
y = x
# 印出 x 和 y 的記憶體位址(id 值應該相同)
print(id(x), id(y))
# 印出 x 和 y 的值
print(x, y)
```
#### ✅ 執行結果(範例):
140706127547120 140706127547120
1 1
你會發現:
- `x` 和 `y` 雖然是兩個變數名稱,但它們實際**指向的是同一個物件(數字 1)**。
- 因此 `id(x) == id(y)` 為 **True**。
#### 📌 核心觀念補充:
- 在 **Python** 中,整數、浮點數、字串等不可變物件(immutable)會被「重用」。
- 當你寫 `y = x`,你只是讓 `y` 這個變數也指向 `x` 所指的那個物件,並沒有複製新的物件。
#### 🧠 延伸練習:
如果你後續修改 `y` 的值,例如:
```python!
y = 2
print(id(x), id(y)) # 這時 id(x) 與 id(y) 就會不同了
```
這代表 `y` 改為指向一個新的整數物件 `2`,而 `x` 仍保持為 `1`。
---
## 2-3 運算子
### 2-3-1 指定運算子
「指定運算子(Assignment Operators)」是在 **Python** 中用來將某個值指定給變數,並且包含 **結合運算(複合指定)** 的功能,例如 `+=`、`-=` 等。
#### 🧪 範例說明:
```python!
x = 10 # x 是 10
x += 5 # 等同 x = x + 5,x 現在是 15
x *= 2 # 等同 x = x * 2,x 現在是 30
x -= 10 # x 現在是 20
x /= 5 # x 現在是 4.0
```
#### 📌 使用情境:
- ✅ 計算累加總和
- ✅ 製作計數器
- ✅ 操作字串或陣列元素時簡化程式
---
### 2-3-2 算術運算子
算術運算子(Arithmetic Operators)是用來執行基本數學運算的符號,像是加減乘除、次方、取餘數等。以下是 Python 中常見的算術運算子與範例整理:
#### 🧮 算術運算子對照表
| 運算子 | 說明 | 範例 | 結果 |
| ---- | ------ | --------- | ----- |
| `+` | 加法 | `5 + 3` | `8` |
| `-` | 減法 | `5 - 2` | `3` |
| `*` | 乘法 | `4 * 2` | `8` |
| `/` | 除法 | `10 / 4` | `2.5` |
| `//` | 整數除法 | `10 // 4` | `2` |
| `%` | 餘數 | `10 % 4` | `2` |
| `**` | 次方(乘冪) | `2 ** 3` | `8` |
#### 🧪 範例程式:
```python!
a = 10
b = 3
print("加法 a + b =", a + b) # 13
print("減法 a - b =", a - b) # 7
print("乘法 a * b =", a * b) # 30
print("除法 a / b =", a / b) # 3.333...
print("整除 a // b =", a // b) # 3
print("餘數 a % b =", a % b) # 1
print("次方 a ** b =", a ** b) # 1000
```
#### ✅ 執行結果(範例):
加法 a + b = 13
減法 a - b = 7
乘法 a * b = 30
除法 a / b = 3.3333333333333335
整除 a // b = 3
餘數 a % b = 1
次方 a ** b = 1000
#### 📌 補充說明:
- `//`:**整除運算子**,只取商的整數部分。
- `%`:**取餘數**,常用於偶數/奇數判斷或週期性計算。
- `**`:**次方運算子**,例如 `2 ** 3` 表示 2 的 3 次方。
---
### 2-3-3 比較運算子
**比較運算子(Comparison Operators)** 用來比較兩個值之間的大小或相等關係,比較結果會回傳布林值 `True` 或 `False`。在 Python 中的比較運算子如下:
#### 📋 比較運算子對照表:
| 運算子 | 說明 | 範例 | 結果 |
| ---- | ----- | -------- | ------ |
| `==` | 等於 | `5 == 5` | `True` |
| `!=` | 不等於 | `5 != 3` | `True` |
| `>` | 大於 | `7 > 3` | `True` |
| `<` | 小於 | `2 < 4` | `True` |
| `>=` | 大於或等於 | `6 >= 6` | `True` |
| `<=` | 小於或等於 | `4 <= 5` | `True` |
#### 🧪 範例程式:
```python!
a = 10
b = 5
print(a == b) # False,a 不等於 b
print(a != b) # True,a 不等於 b
print(a > b) # True,a 大於 b
print(a < b) # False,a 小於 b
print(a >= b) # True,a 大於或等於 b
print(a <= b) # False,a 小於或等於 b
```
#### ✅ 執行結果(範例):
False
True
True
False
True
False
#### ✅ 比較運算子常用情境:
- ✅ 判斷數值相等或大小關係
- ✅ if 條件判斷語句(例如 if x > 0:)
- ✅ 搭配邏輯運算子(如 and, or)做多重條件判斷
#### 🔄 延伸:字串也能比較!
```python!
print("apple" == "apple") # True
print("cat" > "apple") # True(字母順序 c > a)
```
---
### 2-3-4 邏輯運算子
**邏輯運算子(Logical Operators)** 邏輯運算子用來組合多個布林條件,結果依據條件判斷為 `True` 或 `False`,常用於條件判斷和流程控制中。
#### 📋 Python 三大邏輯運算子
| 運算子 | 說明 | 範例 | 解釋 |
| ----- | ----- | -------------------------- | ------------------ |
| `and` | 並且(且) | `True and False` → `False` | 兩邊都為 True 才是 True |
| `or` | 或 | `True or False` → `True` | 只要有一邊為 True 即 True |
| `not` | 非(取反) | `not True` → `False` | 將布林值反轉 |
#### 🧪 範例程式:
```python!
a = 10
b = 5
print(a > 5 and b < 10) # True and True → True
print(a > 5 and b > 10) # True and False → False
print(a > 5 or b > 10) # True or False → True
print(not (a > 5)) # not True → False
```
#### ✅ 執行結果(範例):
True
False
True
False
#### ✅ 應用情境
- 用於 `if` 條件判斷,例如:
```python!
if a > 0 and b > 0:
print("a 和 b 都是正數")
```
- 將多個條件組合起來判斷複雜邏輯。
#### 📌 注意事項
- `and`、`or` 是**短路運算**:遇到結果已確定,就不再繼續判斷。
- `not` 只能用在單一布林值或布林表達式。
---
### 2-3-5 in 與 is 運算子
| 運算子 | 說明 | 舉例 | 結果與補充說明 |
|:------:|----------|----------------------------------------------|----------------|
| `in` | 是否包含 | `x = 1`<br>`y = [1,2,3]`<br>`x in y` | `True`<br>註:`[1,2,3]` 為串列,下一章會介紹 |
| `not in` | 是否不包含 | `x = 1`<br>`y = [1,2,3]`<br>`print(x not in y)` | `False` |
| `is` | 是否為相同物件 | `x = [1,2,3]`<br>`y = [1,2,3]`<br>`print(x is y)` | `False` |
| `is not` | 是否不為相同物件 | `x = [1,2,3]`<br>`y = [1,2,3]`<br>`print(x is not y)` | `True` |
#### `(2-3-5-is.py)` is 運算子
這段程式碼是用來比較兩個 **列表(list)** 變數的記憶體位置與內容相等性。以下是逐行解說與中文註解:
```python!
# 建立一個列表 x,內容為 [1, 2, 3]
x = [1, 2, 3]
# 再建立另一個列表 y,內容也為 [1, 2, 3]
y = [1, 2, 3]
# 印出 x 與 y 的記憶體位置(id)
print(id(x), id(y))
# 使用 is 比較 x 和 y 是否為同一個物件(記憶體位置是否一樣)
print(x is y) # 結果為 False
# 使用 == 比較 x 和 y 的內容是否相等
print(x == y) # 結果為 True
```
#### 🧠 解釋:
| 比較方式 | 說明 | 結果 |
| -------- | --------------------------- | ------- |
| `x is y` | 比較兩個變數是否指向 **同一個記憶體物件**(身份) | `False` |
| `x == y` | 比較兩個物件的 **內容是否相等** | `True` |
- `x` 和 `y` 都是新的 list 物件,即使內容相同,記憶體位址(`id()`)也不同。
- 所以 `x is y` 為 `False`,但 `x == y` 為 `True`。
#### ✅ 範例輸出(會依系統記憶體配置而異):
140262717719744 140262717720448
False
True
#### 📌 延伸說明:
如果你寫的是:
```python!
y = x
```
那麼 `x is y` 就會變成 `True`,因為它們指向同一個 **list**。
---
## 2-4 字串
### `(2-4-string1.py)` 使用單引號「'」與雙引號「"」所包夾的文字,在 **Python** 會被視為字串
這段程式碼示範了 Python 字串的基本建立方法:使用單引號 `'...'`、雙引號 `"..."`、以及三重引號 `'''...'''`(或 `"""..."""`)來處理不同情況的文字。以下是逐行說明與中文註解版本:
```python!
# 使用單引號建立一行字串
s1 = '春眠不覺曉,處處聞啼鳥。'
print(s1)
# 輸出:春眠不覺曉,處處聞啼鳥。
```
```python!
# 使用雙引號建立另一行字串
s2 = "夜來風雨聲,花落知多少。"
print(s2)
# 輸出:夜來風雨聲,花落知多少。
```
```python!
# 單引號字串中包含雙引號內容,這樣寫是合法的
s3 = '作者"孟浩然" 詩名"春曉"'
print(s3)
# 輸出:作者"孟浩然" 詩名"春曉"
```
```python!
# 雙引號字串中包含單引號內容,也完全沒問題
s4 = "作者'孟浩然' 詩名'春曉'"
print(s4)
# 輸出:作者'孟浩然' 詩名'春曉'
```
```python!
# 使用三重單引號建立多行字串(可以跨行、保留換行與空格)
s5 = ''' 春眠不覺曉,處處聞啼鳥。
夜來風雨聲,花落知多少。
作者"孟浩然" 詩名"春曉"
'''
print(s5)
```
#### 📌 三重引號 `'''...'''` 或 `"""..."""` 的特點:
- 可用來建立「多行字串」。
- 保留原始的 **換行符號與縮排空格**。
- 適合用來寫詩、文章、註解段落、長文字。
#### ✅ 輸出範例(含換行):
春眠不覺曉,處處聞啼鳥。
夜來風雨聲,花落知多少。
作者"孟浩然" 詩名"春曉"
---
### `(2-4-1-string2.py)` 字串運算子
這段程式碼展示了 **Python 字串的串接、重複、索引、切片**與**轉向技巧**,也包含了特殊字元如 `\n`(換行)、`\t`(跳格/tab)的應用。以下是詳細中文註解與對照範例:
#### 🔹 字串串接與重複
```python!
s1 = '01234'
s2 = '56789'
s3 = s1 + s2 # 串接字串 s1 和 s2
print(s3) # 輸出:0123456789
```
```python!
s1 = '01234'
s2 = s1 * 2 # 重複 s1 兩次
print(s2) # 輸出:0123401234
```
#### 🔹 字串索引與切片
**切片(slice)** 語法 `s[start:end:step]`
```python!
s = '0123456789'
print('s=', s, 's[0]=', s[0]) # 第一個字元:0
print('s=', s, 's[1]=', s[1]) # 第二個字元:1
print('s=', s, 's[-1]=', s[-1]) # 最後一個字元:9
print('s=', s, 's[-2]=', s[-2]) # 倒數第二個字元:8
print('s=', s, 's[:]=', s[:]) # 全部切出:0123456789
print('s=', s, 's[5:]=', s[5:]) # 從第 5 個位置開始到結尾:56789
print('s=', s, 's[-2:]=', s[-2:]) # 從倒數第 2 位到結尾:89
print('s=', s, 's[:5]=', s[:5]) # 從開頭到第 4 位(不含第5):01234
print('s=', s, 's[:-2]=', s[:-2]) # 從開頭到倒數第 3 位(不含倒數2):01234567
print('s=', s, 's[7:9]=', s[7:9]) # 第 7 到第 8 位(不含9):78
print('s=', s, 's[-4:-1]=', s[-4:-1]) # 倒數第 4 到倒數第 2 位(不含-1):678
print('s=', s, 's[5:-2]=', s[5:-2]) # 第 5 到倒數第 3 位(不含倒數2):567
print('s=', s, 's[2:10:2]=', s[2:10:2]) # 每隔 2 個字元取值(從第 2 到第 9):2468
print('s=', s, 's[::-1]=', s[::-1]) # 整串反轉:9876543210
print('s=', s, 's[-1::-1]=', s[-1::-1]) # 同上,從最後一位倒著取到第一位:9876543210
```
#### ✅ 執行結果(範例):
s= 0123456789 s[0]= 0
s= 0123456789 s[1]= 1
s= 0123456789 s[-1]= 9
s= 0123456789 s[-2]= 8
s= 0123456789 s[:]= 0123456789
s= 0123456789 s[5:]= 56789
s= 0123456789 s[-2:]= 89
s= 0123456789 s[:5]= 01234
s= 0123456789 s[:-2]= 01234567
s= 0123456789 s[7:9]= 78
s= 0123456789 s[-4:-1]= 678
s= 0123456789 s[5:-2]= 567
s= 0123456789 s[2:10:2]= 2468
s= 0123456789 s[::-1]= 9876543210
s= 0123456789 s[-1::-1]= 9876543210
補充:
```python!
print(s[-2::])
```
- `s[-2::]` 是使用 **切片語法** `s[start:end:step]`:
- `start = -2` → 從倒數第 2 個字元開始(也就是字元 `'8'`)
- `end` 省略 → 代表切到最後
- `step = 1`(預設)→ 正向一個一個取
✅ 結果輸出:
89
📘 延伸說明:
| 表達式 | 結果 | 說明 |
| ----------- | ---------- | ---------------- |
| `s[-2::]` | `'89'` | 從 `'8'` 開始,一直到最後 |
| `s[-2::-1]` | `'87...0'` | 從 `'8'` 開始向前倒著取 |
| `s[1:-2:3]` | `'147'` | 從 `'1'` 開始每隔 `3` 個字元取到倒數2 (`'8'`) (不含倒數2 `'8'`) |
```python!
print(s[:-5])
```
是在使用 **Python** 的 **字串切片(slice)** 語法,格式是 `s[start:end]`。
🔍 解讀 `s[:-5]`
- `s = '0123456789'`
- `start`:預設為 `0`(從開頭)
- `end = -5`:表示切到 **倒數第 5 個字元的「前一個」位置**
- `step`:省略,預設為 `1`(正向)
📤 輸出結果:
01234
#### 🔹 多行字串 + 特殊字元
```python!
s = '春眠不覺曉,處處聞啼鳥。\n\
夜來風雨聲,花落知多少。\n\
\t作者"孟浩然" 詩名"春曉"'
print(s)
```
##### 📌 說明:
- `\n`:換行
- `\t`:Tab 鍵(縮排)
- 多行用 `\` 續行,也可以改用 `'''...'''` 寫法更直觀
##### ✅ 輸出結果:
```arduino!
春眠不覺曉,處處聞啼鳥。
夜來風雨聲,花落知多少。
作者"孟浩然" 詩名"春曉"
```
#### 📘 小結:常見字串操作
| 操作 | 範例 | 結果 |
| -- | -------------- | ---------- |
| 串接 | `'ab' + 'cd'` | `'abcd'` |
| 重複 | `'ha' * 3` | `'hahaha'` |
| 索引 | `'abc'[1]` | `'b'` |
| 切片 | `'abcde'[1:4]` | `'bcd'` |
| 反轉 | `'abc'[::-1]` | `'cba'` |
---
### `(2-4-2-string3.py)` 字串的內建函式
這段程式碼展示了 **Python 字串處理的多種常用方法**,包含分割、合併、取代、搜尋、格式對齊、大小寫轉換、補零、去除空白等功能。以下是完整的中文註解與說明:
#### **🔹 分割字串 `split()` + 合併字串 `join()`**
```python!
s1 = '春眠不覺曉,處處聞啼鳥,夜來風雨聲,花落知多少。'
list1 = s1.split(',') # 以「,」切割字串,產生清單
print(list1) # 輸出:['春眠不覺曉', '處處聞啼鳥', '夜來風雨聲', '花落知多少。']
s2 = ','.join(list1) # 用「,」把 list1 重新組合成字串
print(s2) # 輸出:春眠不覺曉,處處聞啼鳥,夜來風雨聲,花落知多少。
```
##### ✅ 輸出結果:
['春眠不覺曉', '處處聞啼鳥', '夜來風雨聲', '花落知多少。']
春眠不覺曉,處處聞啼鳥,夜來風雨聲,花落知多少。
#### 🔹 字串取代 `replace()`
```python!
s3 = s1.replace('春', '冬') # 把字串中第一個 '春' 換成 '冬'
print(s3) # 輸出:冬眠不覺曉,處處聞啼鳥,夜來風雨聲,花落知多少。
```
##### ✅ 輸出結果:
冬眠不覺曉,處處聞啼鳥,夜來風雨聲,花落知多少。
#### 🔹 查找字串位置` find()`、`rfind()`
```python!
print("s1為", s1, '在s1的', s1.find('花落'), '位置發現"花落"')
# find() 從左邊開始找子字串的位置(回傳起始索引)
print("s1為", s1, '在s1中從右邊數過來第一個出現"處"的位置為', s1.rfind('處'))
# rfind() 從右邊開始找子字串的位置(回傳起始索引)
```
##### ✅ 輸出結果:
s1為 春眠不覺曉,處處聞啼鳥,夜來風雨聲,花落知多少。 在s1的 18 位置發現"花落"
s1為 春眠不覺曉,處處聞啼鳥,夜來風雨聲,花落知多少。 在s1中從右邊數過來第一個出現"處"的位置為 7
#### 🔹 開頭結尾檢查 `startswith()`、`endswith()`
```python!
print(s1.startswith('春眠')) # 檢查 s1 是否以 "春眠" 開頭 → True
print(s1.endswith('多少。')) # 檢查 s1 是否以 "多少。" 結尾 → True
```
##### ✅ 輸出結果:
True
True
#### 🔹 子字串出現次數 `count()`
```python!
print('s1=', s1, "s1.count('處')等於", s1.count('處'))
# 計算 "處" 出現幾次 → 2 次
```
##### ✅ 輸出結果:
s1= 春眠不覺曉,處處聞啼鳥,夜來風雨聲,花落知多少。 s1.count('處')等於 2
#### 🔹 對齊格式(寬度10)
```python!
s1 = '春眠不覺曉'
print(s1.center(10)) # 置中對齊 → 空白填滿左右
print(s1.rjust(10)) # 靠右對齊
print(s1.ljust(10)) # 靠左對齊
```
##### ✅ 輸出結果:
春眠不覺曉
春眠不覺曉
春眠不覺曉
#### 🔹 英文字串轉換大小寫
```python!
s1 = 'An apple a day.'
print(s1.capitalize()) # 首字大寫 → An apple a day.
print(s1.title()) # 每個單字首字大寫 → An Apple A Day.
print(s1.swapcase()) # 大小寫互換 → aN APPLE A DAY.
print(s1.upper()) # 全部轉大寫 → AN APPLE A DAY.
print(s1.lower()) # 全部轉小寫 → an apple a day.
```
##### ✅ 輸出結果:
An apple a day.
An Apple A Day.
aN APPLE A DAY.
AN APPLE A DAY.
an apple a day.
#### 🔹 數字補零 `zfill()`
```python!
s1 = '123'
print(s1.zfill(5)) # 左側補零至長度 5 → 00123
```
##### ✅ 輸出結果:
00123
#### 🔹 去除空白字元(或自訂字元)
```python!
s1 = ' Hello,Mary. '
print(s1.strip()) # 去除左右兩側空白 → Hello,Mary.
print(s1.lstrip(' H')) # 去除左側的 ' ' 和 'H' → ello,Mary.
print(s1.rstrip(' .')) # 去除右側的空白與句點 → Hello,Mary
```
##### ✅ 輸出結果:
Hello,Mary.
ello,Mary.
Hello,Mary
#### ✅ 小結:常用字串處理函式功能速查
| 函式名 | 功能描述 |
| -------------- | ------------- |
| `split()` | 分割字串為清單 |
| `join()` | 將清單合併為字串 |
| `replace()` | 替換字串中的子字串 |
| `find()` | 從左找子字串的位置 |
| `rfind()` | 從右找子字串的位置 |
| `count()` | 統計子字串出現次數 |
| `startswith()` | 是否以某字串開頭 |
| `endswith()` | 是否以某字串結尾 |
| `center()` | 置中對齊字串(寬度) |
| `ljust()` | 靠左對齊 |
| `rjust()` | 靠右對齊 |
| `capitalize()` | 首字母大寫 |
| `title()` | 每個單字首字母大寫 |
| `upper()` | 全部大寫 |
| `lower()` | 全部小寫 |
| `swapcase()` | 大小寫互換 |
| `zfill()` | 左邊補零(常用於數字格式) |
| `strip()` | 去除兩側空白或指定字元 |
| `lstrip()` | 去除左側空白或指定字元 |
| `rstrip()` | 去除右側空白或指定字元 |
---
## 2-5 範例練習
### `(2-5-1-服裝訂購系統.py)`
這段程式碼是一個簡單的 **服裝訂購總金額計算器**,讓使用者輸入上衣、褲子、背心的數量,然後計算總價。以下是加上中文註解的版本:
```python!
# 輸入上衣數量,轉換為整數型態並存入變數「上衣」
上衣 = int(input('請輸入上衣數量?'))
# 輸入褲子數量,轉換為整數型態並存入變數「褲子」
褲子 = int(input('請輸入褲子數量?'))
# 輸入背心數量,轉換為整數型態並存入變數「背心」
背心 = int(input('請輸入背心數量?'))
# 計算總金額(上衣單價300、褲子350、背心400)
總金額 = 上衣 * 300 + 褲子 * 350 + 背心 * 400
# 輸出結果
print('訂購服裝的總金額為', 總金額)
```
#### ✅ 輸出結果:
請輸入上衣數量?2
請輸入褲子數量?3
請輸入背心數量?1
訂購服裝的總金額為 2050
#### 🧮 範例輸入與輸出:
假設使用者輸入:
請輸入上衣數量?2
請輸入褲子數量?1
請輸入背心數量?3
則輸出為:
訂購服裝的總金額為 2150
#### ✅ 延伸建議(進階版本):
你也可以用 `f-string` 讓輸出更整齊:
```python!
print(f"訂購服裝的總金額為 {總金額} 元")
```
---
### `(2-5-2-計算圓面積與圓周長.py)`
這段程式碼是用來**計算圓的周長與面積**,根據使用者輸入的半徑,使用圓周率公式進行運算。下面是詳細的**中文註解版本**:
```python!
# 讓使用者輸入半徑,轉為浮點數型別(小數也可以輸入)
半徑 = float(input('請輸入半徑?'))
# 設定圓周率常數(π)
PI = 3.14159
# 計算圓周長:公式為 2 × π × 半徑
圓周長 = 2 * PI * 半徑
# 計算圓面積:公式為 π × 半徑²
圓面積 = 半徑 * 半徑 * PI
# 輸出結果(不限制小數點位數)
print('圓周長為', 圓周長, '圓面積為', 圓面積)
```
#### ✅ 輸出結果:
請輸入半徑?10
圓周長為 62.8318 圓面積為 314.159
#### 🧮 範例輸入與輸出:
如果輸入:
請輸入半徑?5
則輸出結果為:
圓周長為 31.4159 圓面積為 78.53975
#### ✅ 加強版本建議(含小數點格式化):
如果你想讓數字顯示更整齊,例如保留小數點 2 位,可以這樣寫:
```python!
print(f'圓周長為 {圓周長:.2f},圓面積為 {圓面積:.2f}')
```
輸出:
圓周長為 31.42,圓面積為 78.54
### `(2-5-3-攝氏轉華氏.py)`
這段程式碼是用來**將攝氏溫度轉換為華氏溫度**,是非常常見的單位轉換應用。以下是加上清楚中文註解的版本:
```python!
# 讓使用者輸入攝氏溫度,並轉換為浮點數型態
c = float(input('請輸入攝氏溫度?'))
# 溫度轉換公式:華氏 = 攝氏 × 9/5 + 32
f = c * 9 / 5 + 32
# 輸出結果
print('華氏溫度為', f)
```
#### 🧮 公式回顧:
$$
°F \ = \ °C \ × \ \frac{9}{5} \ + \ 32
$$
#### ✅ 範例輸入與輸出:
假設使用者輸入:
請輸入攝氏溫度?25
輸出:
華氏溫度為 77.0
#### 🔧 建議格式化輸出(小數點顯示更清楚):
```python!
print(f'攝氏 {c:.1f} 度 = 華氏 {f:.1f} 度')
```
輸出結果:
攝氏 25.0 度 = 華氏 77.0 度
### `(2-5-4-複利計算.py)`
這段程式碼是用來計算 **本金加年利率的複利結果**,也就是**每年利息會計入本金繼續計算**,屬於「複利計算」的範例。以下是加上詳細中文註解的版本:
#### ✅ 加註解版本:
```python!
# 輸入本金(整數型別)
money = int(input('請輸入本金?'))
# 輸入年利率(百分比形式),轉換為浮點數
interest = float(input('請輸入年利率(%)?'))
# 計算第1年本利和:本金 × (1 + 年利率)
y1 = money * (1 + interest / 100)
# 計算第2年本利和:本金 × (1 + 年利率)^2
y2 = money * ((1 + interest / 100) ** 2)
# 計算第3年本利和:本金 × (1 + 年利率)^3
y3 = money * ((1 + interest / 100) ** 3)
# 輸出三年的本利和
print('第一年本利和為', y1)
print('第二年本利和為', y2)
print('第三年本利和為', y3)
```
##### 🧮 複利公式小提醒:
$$
A \ = \ P \ × \ (1+r)^n
$$
- `A`:本利和(總金額)
- `P`:本金
- `r`:年利率(百分比需除以 100)
- `n`:年數
#### 🧪 範例輸入:
請輸入本金?10000
請輸入年利率(%)?5
#### 🧾 輸出結果:
第一年本利和為 10500.0
第二年本利和為 11025.0
第三年本利和為 11576.25
### `(2-5-5-迴文.py)`
這段程式碼是用來**判斷輸入的字串是否為「迴文」(Palindrome)**,非常簡潔有效!下面是加上中文註解的版本:
```python!
# 輸入一個字串
s = input('請輸入一個字串?')
# 反轉字串:s[::-1] 是從右邊開始以-1步長反向切片
# 判斷字串是否與其反轉後相等
print('迴文判斷結果為', s == s[::-1])
```
#### ✅ 輸出結果:
```sgraphql!
請輸入一個字串? abvba
迴文判斷結果為 True
```
#### 📌 什麼是迴文?
迴文是指「正著讀和反著讀都一樣」的字串,例如:
- `"abba"`
- `"12321"`
- `"上海自來水來自海上"`(中文也成立)
#### 🧪 範例輸入與輸出:
**輸入:**
請輸入一個字串?12321
**輸出:**
迴文判斷結果為 True
#### ✅ 延伸:忽略大小寫與空白
如果你想進階處理「忽略大小寫、空白與標點」,可用以下改進版:
```python!
import re # 匯入正則表示式模組(regular expression)
# 使用者輸入字串
s = input('請輸入一個字串?')
# 用正則表達式過濾掉所有「不是」中英文與數字的字元
# ^ 表示取反,[] 是字元集合,a-zA-Z0-9 是英文和數字,一-龥 是常見中文字範圍
# re.sub() 表示將匹配到的字元「替換成空字串」
s_clean = re.sub(r'[^a-zA-Z0-9一-龥]', '', s).lower()
# 判斷處理後的字串是否為迴文(與反轉後結果相同)
print('迴文判斷結果為', s_clean == s_clean[::-1])
```
#### 📘 支援中英文、忽略標點與大小寫,例如 `"A man, a plan, a canal: Panama"` 也能判斷為 True。
#### ✅ 範例測試:
```text!
請輸入一個字串?A man, a plan, a canal: Panama
迴文判斷結果為 True
```
```text!
請輸入一個字串?上海自來水來自海上
迴文判斷結果為 True
```
#### 📌 重點技巧解析:
+ `re.sub(r'[^a-zA-Z0-9一-龥]', '', s)`:
- 移除所有非中英文與數字
+ `.lower()`:將字串轉小寫(忽略大小寫差異)
+ `s[::-1]`:反轉字串(Python 切片技巧)
#### 🧠 正則表達式說明:
```regex!
[^a-zA-Z0-9一-龥]
```
+ `^`:非
+ `a-zA-Z`:英文大小寫
+ `0-9`:阿拉伯數字
+ `一-龥`:常見的中文字範圍(不含全部罕用字)
這樣可以**保留中英文與數字,排除標點、空格與符號**。
如果你想把它改寫成一個可重複使用的函式,可以這樣寫:
```python!
def is_palindrome(s):
s_clean = re.sub(r'[^a-zA-Z0-9一-龥]', '', s).lower()
return s_clean == s_clean[::-1]
```