Python 課程 – 資料結構:清單(list)
主題:append / extend / insert / pop / remove
簡介
在 Python 中,清單(list) 是最常使用的可變序列資料型別。它支援動態增減元素、隨機存取以及多種內建方法,讓程式設計師能輕鬆處理各種集合資料。
本單元聚焦於五個最常見的清單操作:append、extend、insert、pop、remove。了解它們的差異與正確使用時機,對於寫出可讀性高、效能佳的程式碼至關重要。
為什麼要特別學習這五個方法?
append、extend、insert負責 向清單寫入 資料。pop、remove則是 從清單刪除 資料的主要工具。
正確選擇與搭配使用,能避免不必要的時間與記憶體開銷,並減少常見的錯誤(例如刪除錯誤的元素或產生意外的參照關係)。
核心概念
1. list.append(obj)
append 會把 單一物件 加到清單最尾端,操作是 原位(in‑place) 的,也就是說原本的清單會被直接修改,並不會回傳新清單。
# 範例 1:基本用法
fruits = ['apple', 'banana']
fruits.append('cherry')
print(fruits) # ['apple', 'banana', 'cherry']
# 範例 2:加入另一個 list 本身(會變成子清單)
numbers = [1, 2, 3]
numbers.append([4, 5])
print(numbers) # [1, 2, 3, [4, 5]]
小提醒:
append只接受 一個 參數,若想一次加入多個元素,請改用extend。
2. list.extend(iterable)
extend 會把 可疊代物件(iterable) 中的每個元素逐一加入清單尾端,同樣是原位修改。這是 展開 另一個序列的最佳方式。
# 範例 3:將另一個 list 的元素展開加入
a = [1, 2]
b = [3, 4, 5]
a.extend(b)
print(a) # [1, 2, 3, 4, 5]
# 範例 4:使用字串、集合或產生器
c = ['x', 'y']
c.extend('zpq') # 字串會被視為字元序列
print(c) # ['x', 'y', 'z', 'p', 'q']
d = set([10, 20])
c.extend(d) # 集合的元素順序不保證
print(c)
為什麼
extend常比多次append效率高?
每次append可能會觸發清單的重新配置(reallocation),而extend會一次性計算總長度,減少記憶體搬移的次數。
3. list.insert(index, obj)
insert 可以在 任意位置 插入單一物件。index 若超出範圍,會自動調整到最前或最後。
# 範例 5:在中間插入元素
colors = ['red', 'blue']
colors.insert(1, 'green') # 在索引 1 前插入
print(colors) # ['red', 'green', 'blue']
# 範例 6:負索引與超界插入
colors.insert(-1, 'yellow') # 插入到倒數第二個位置前
colors.insert(100, 'purple')# 超過長度,直接加到最後
print(colors) # ['red', 'green', 'yellow', 'blue', 'purple']
注意:
insert會把插入位置之後的所有元素往後搬移,若清單很長,頻繁使用會產生 O(n) 的時間成本。
4. list.pop([index])
pop 會 移除並回傳 指定位置的元素,預設是最後一個(index=-1)。如果清單為空,會拋出 IndexError。
# 範例 7:彈出最後一個元素
stack = [10, 20, 30]
last = stack.pop()
print(last) # 30
print(stack) # [10, 20]
# 範例 8:彈出任意位置
stack.insert(0, 5)
mid = stack.pop(1) # 移除索引 1 的元素 (10)
print(mid) # 10
print(stack) # [5, 20]
實務技巧:
pop常用於 堆疊(stack) 的實作,因為它只涉及尾端操作,時間複雜度為 O(1)。
5. list.remove(value)
remove 會搜尋 第一個 與 value 相等的元素並將其刪除,若找不到則拋出 ValueError。它不回傳被刪除的項目。
# 範例 9:刪除指定值
items = ['a', 'b', 'c', 'b']
items.remove('b') # 只會刪除第一個 'b'
print(items) # ['a', 'c', 'b']
# 範例 10:錯誤處理
try:
items.remove('x')
except ValueError:
print('元素不存在!')
提醒:
remove會遍歷整個清單直到找到目標,最壞情況下是 O(n)。若需要大量刪除,考慮使用 列表推導式 或 集合(set) 來加速。
常見陷阱與最佳實踐
| 陷阱 | 說明 | 建議做法 |
|---|---|---|
把 append 當成 extend |
list.append([1,2]) 會產生子清單,非預期的結構。 |
若要一次加入多個元素,使用 extend;若真的需要子清單,才用 append。 |
在迴圈中同時 remove |
直接遍歷清單並刪除會導致索引錯位,部分元素會被跳過。 | 使用 倒序迴圈 (for i in range(len(lst)-1, -1, -1)) 或 列表推導式 產生新清單。 |
大量 insert 到前端 |
每次插入都會搬移整個清單,效能低下。 | 若需要頻繁在頭部操作,可改用 collections.deque。 |
忘記檢查空清單再 pop |
空清單直接 pop() 會拋 IndexError。 |
在彈出前使用 if mylist: 判斷或捕獲例外。 |
remove 失敗未捕獲 |
找不到元素時會中斷程式。 | 先用 if value in mylist: 判斷,或使用 try/except。 |
最佳實踐小結:
- 選對方法:
append單一、extend多個、insert指定位置。 - 盡量避免在大清單前端插入或刪除,改用
deque或重新建構清單。 - 使用例外處理 或事前檢查,提升程式的魯棒性。
- 記得操作是原位的,若需要保留原始清單,先
copy()。
實際應用場景
1. 堆疊(Stack)實作
class Stack:
def __init__(self):
self._data = []
def push(self, item):
self._data.append(item) # O(1)
def pop(self):
if not self._data:
raise IndexError('pop from empty stack')
return self._data.pop() # O(1)
def peek(self):
return self._data[-1] if self._data else None
2. 合併多筆資料
# 從多個 CSV 檔讀取資料,合併成單一清單
all_rows = []
for filename in ['a.csv', 'b.csv', 'c.csv']:
with open(filename) as f:
rows = f.read().splitlines()
all_rows.extend(rows) # 一次展開加入
3. 事件排程(Queue)— 使用 pop(0)(不建議) vs deque
from collections import deque
queue = deque()
queue.append('task1')
queue.append('task2')
first = queue.popleft() # O(1) 取出最前面的任務
若改用 list.pop(0),每次都會搬移整個清單,效能會退化。
4. 清除重複或不需要的元素
raw = ['apple', 'banana', 'apple', 'cherry', 'banana']
# 移除所有出現超過一次的元素
unique = []
for item in raw:
if item not in unique:
unique.append(item) # 使用 append 建立新清單
print(unique) # ['apple', 'banana', 'cherry']
總結
本單元針對 append、extend、insert、pop、remove 五個清單方法進行了深入說明與實作範例。掌握它們的行為差異與效能特性,能讓你:
- 正確選擇 資料寫入 或 刪除 的方式,避免不必要的時間與記憶體浪費。
- 在實務開發中以 堆疊、佇列、資料合併 等常見情境快速構築穩定的程式邏輯。
- 識別常見陷阱,運用例外處理與最佳實踐提升程式的可讀性與魯棒性。
只要熟練這幾個方法,清單的使用將變得得心應手,為日後學習更進階的資料結構(如 dict、set、deque)奠定堅實基礎。祝你在 Python 的世界裡玩得開心、寫得更好!