Python 資料結構 – 清單(list)
建立、索引、切片
簡介
在 Python 中,**清單(list)**是最常使用、也是最彈性的序列型別之一。無論是臨時儲存使用者輸入、處理檔案資料,或是實作演算法的中間結果,清單都扮演關鍵角色。
掌握清單的 建立、索引 與 切片,不僅能讓程式碼更簡潔,也能提升執行效率,對於從初學者晉升為中級開發者而言,是不可或缺的基礎功。
本篇文章將以 繁體中文(台灣) 為語言,從概念說明、實作範例、常見陷阱到實務應用,完整呈現清單的核心操作,讓讀者能在寫程式時得心應手。
核心概念
1️⃣ 清單的建立
Python 提供多種方式建立清單:
| 建立方式 | 說明 |
|---|---|
直接使用方括號 [] |
最常見、語意直觀 |
list() 內建函式 |
可將其他可迭代物件轉為清單 |
| 列表生成式(list comprehension) | 以簡潔的語法一次產生多筆資料 |
範例 1:基本建立
# 直接使用方括號
numbers = [1, 2, 3, 4, 5]
# 使用 list() 轉換字串為字元清單
chars = list("Python")
# 列表生成式:產生 0~9 的平方數
squares = [x**2 for x in range(10)]
print(numbers) # [1, 2, 3, 4, 5]
print(chars) # ['P', 'y', 't', 'h', 'o', 'n']
print(squares) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
註解:
- 方括號內的元素可以是任意型別,甚至可以混合不同型別。
list()會把可迭代物件(如字串、元組、集合)逐一取出成為清單元素。- 列表生成式的語法
[...] for ... in ...,可配合條件表達式過濾資料。
2️⃣ 清單的索引(Index)
清單支援 零基礎索引,也就是第一個元素的索引為 0。負數索引則從尾端開始計算,-1 表示最後一個元素。
範例 2:正向與負向索引
fruits = ["蘋果", "香蕉", "櫻桃", "芒果"]
# 正向索引
first = fruits[0] # "蘋果"
third = fruits[2] # "櫻桃"
# 負向索引
last = fruits[-1] # "芒果"
second_last = fruits[-2] # "櫻桃"
print(first, third, last, second_last)
# 蘋果 櫻桃 芒果 櫻桃
小技巧:
- 若索引超出範圍,會拋出
IndexError。可以先用len(list)檢查長度,或使用try/except捕捉例外。
3️⃣ 清單的切片(Slice)
切片 允許一次取出連續的一段子清單,語法為 list[start:stop:step],其中:
start:起始索引(含),預設為0。stop:結束索引(不含),預設為清單長度。step:步長,預設為1,可為負數實現反向切片。
範例 3:基本切片
numbers = list(range(1, 11)) # [1, 2, ..., 10]
# 取得第 2~5 個元素(索引 1~4)
sub1 = numbers[1:5] # [2, 3, 4, 5]
# 省略 start,從開頭到第 4 個元素(不含索引 4)
sub2 = numbers[:4] # [1, 2, 3, 4]
# 省略 stop,從第 6 個元素到結尾
sub3 = numbers[5:] # [6, 7, 8, 9, 10]
# 使用 step = 2,取出奇數位置的元素
sub4 = numbers[::2] # [1, 3, 5, 7, 9]
# 反向切片,取得倒序清單
sub5 = numbers[::-1] # [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
print(sub1, sub2, sub3, sub4, sub5, sep="\n")
範例 4:切片與賦值(修改子清單)
letters = ['a', 'b', 'c', 'd', 'e']
# 把索引 1~3 的元素換成 X、Y、Z
letters[1:4] = ['X', 'Y', 'Z']
print(letters) # ['a', 'X', 'Y', 'Z', 'e']
# 使用步長替換偶數位置的元素
letters[::2] = ['1', '2', '3']
print(letters) # ['1', 'X', '2', 'Z', '3']
說明:切片左側可以直接賦值,長度不必相同,Python 會自動調整清單大小。
4️⃣ 常用的清單操作(補充)
| 方法 | 功能 |
|---|---|
append(item) |
在尾端加入單一元素 |
extend(iterable) |
把另一個可迭代物件的所有元素接在尾端 |
insert(index, item) |
在指定位置插入元素 |
pop([index]) |
移除並返回指定索引的元素,預設最後一個 |
remove(item) |
移除第一個出現的指定值 |
clear() |
清空清單 |
sort(key=None, reverse=False) |
原位排序 |
sorted(list, ...) |
回傳排序後的新清單 |
範例 5:結合索引與方法
data = [10, 20, 30, 40]
# 在索引 2 前插入 25
data.insert(2, 25) # [10, 20, 25, 30, 40]
# 移除最後一筆資料並取得它
last = data.pop() # last = 40, data = [10, 20, 25, 30]
# 把另一個清單合併進來
data.extend([50, 60])
print(data) # [10, 20, 25, 30, 50, 60]
常見陷阱與最佳實踐
| 陷阱 | 說明 | 最佳實踐 |
|---|---|---|
| 共享同一個清單物件 | a = [] ; b = a 會讓 a、b 指向同一個清單,修改其中一個會影響另一個。 |
使用 b = a.copy() 或 b = list(a) 產生獨立副本。 |
| 切片返回新清單 | sub = lst[1:3] 產生的是 新 清單,對 sub 的修改不會影響原清單。 |
若要就地修改,使用切片賦值 lst[1:3] = [...]。 |
| 負索引超出範圍 | lst[-len(lst)-1] 會拋 IndexError。 |
先檢查長度或使用 try/except。 |
| 步長為 0 | lst[::0] 會產生 ValueError: slice step cannot be zero。 |
確保 step 不為 0,或在計算前先驗證。 |
| 不必要的多層巢狀迴圈 | 使用列表生成式或內建函式(如 sum, any, all)可降低複雜度。 |
優先考慮 list comprehension、map、filter。 |
小提醒:在大量資料處理時,盡量避免在迴圈內不斷呼叫 list.append(),改用列表生成式或一次性建立完整清單,可減少記憶體重新配置的開銷。
實際應用場景
資料清理
讀取 CSV 檔後,常需要把某欄位的字串切割、取子集或重新排序。利用切片與列表生成式,可快速產生乾淨的資料清單。簡易快取(Cache)
使用清單作為 LRU(Least Recently Used)快取的實作,只需pop(0)移除最舊項目,append(item)新增最新項目。遊戲開發 – 角色指令序列
玩家的指令可以存成清單,透過切片取得最近的 N 步驟,或使用[::-1]逆向檢查歷史行為。演算法練習 – 滑動視窗
在字串或數列問題中,滑動視窗常以切片lst[i:i+k]實作,簡潔且效能佳。機器學習前處理
把文字資料切成 n-gram、把圖像像素展平成一維清單,都是透過list()與切片完成的基礎步驟。
總結
- 建立:使用方括號、
list()、列表生成式,依需求選擇最直觀或最高效的方式。 - 索引:零基礎索引與負向索引讓存取任意位置變得簡單,務必留意範圍檢查以避免
IndexError。 - 切片:
list[start:stop:step]是取子清單、反向、跳躍取樣的強大工具,並支援賦值以就地修改。 - 最佳實踐:避免共享同一個清單物件、合理使用切片返回新清單或就地修改、檢查步長與索引的合法性。
掌握以上概念後,你將能在 Python 專案中自如地操作清單,從簡單的資料收集到複雜的演算法實作,都能以清晰、效能佳的方式完成。祝你寫程式愉快,持續探索 Python 更深層的可能性!