---
# System prepended metadata

title: Python - ch.02 資料型別、變數與運算子

---

# 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]
```