元組(Tuple)#
元組(Tuple)與串列相似,可以儲存多個有序的元素,但 建立後不能修改 (不可變,immutable):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| # 建立元組
t1 = (1, 2, 3)
t2 = ("apple", "banana", "cherry")
t3 = (1, "hello", 3.14, True) # 可混合型別
# 單一元素的元組:必須加逗號!
single = (42,)
print(type(single)) # <class 'tuple'>
# 沒有逗號只是括號,不是 tuple
not_tuple = (42)
print(type(not_tuple)) # <class 'int'>
# 也可以不用括號
t4 = 1, 2, 3
print(type(t4)) # <class 'tuple'>
|
存取與查詢#
元組支援大部分 不修改 的串列操作:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| t = (10, 20, 30, 40, 50)
# 索引與切片
print(t[0]) # 10
print(t[-1]) # 50
print(t[1:4]) # (20, 30, 40)
# 查詢
print(30 in t) # True
print(t.count(20)) # 1
print(t.index(30)) # 2
print(len(t)) # 5
# 迭代
for item in t:
print(item)
|
解包(Unpacking)#
元組最實用的特性之一是可以直接解包到多個變數:
1
2
3
4
| t = (10, 20, 30, 40, 50)
a, b, c, d, e = t
print(a, b, c) # 10 20 30
|
星號解包#
1
2
3
4
5
6
7
8
9
| # 剩餘元素收集到串列
first, *rest = (1, 2, 3, 4, 5)
print(first) # 1
print(rest) # [2, 3, 4, 5]
first, *middle, last = (1, 2, 3, 4, 5)
print(first) # 1
print(middle) # [2, 3, 4]
print(last) # 5
|
交換兩個變數#
利用元組解包,可以不需要暫存變數就完成交換:
1
2
3
| x, y = 10, 20
x, y = y, x
print(x, y) # 20 10
|
元組 vs 串列#
| 特性 | 元組 tuple | 串列 list |
|---|
| 是否可修改 | 否(不可變) | 是(可變) |
| 語法 | (1, 2, 3) | [1, 2, 3] |
| 可做字典的 key | 是 | 否 |
| 記憶體用量 | 較少 | 較多 |
| 適合情境 | 固定資料、多值回傳 | 動態增減的資料 |
何時使用元組?#
固定不變的資料#
1
2
3
| # 座標、RGB 顏色等語意上不應該被修改的資料
position = (25.0, 121.5) # 緯度、經度
color = (255, 128, 0) # RGB 值
|
函式回傳多個值#
函式 return 多個值時,實際上回傳的就是 tuple:
1
2
3
4
5
6
7
8
9
| def min_max(numbers):
return min(numbers), max(numbers)
lo, hi = min_max([3, 1, 4, 1, 5, 9])
print(lo, hi) # 1 9
# 確認回傳型別
result = min_max([3, 1, 4])
print(type(result)) # <class 'tuple'>
|
作為字典的 key#
因為 tuple 不可變,所以可以雜湊(hashable),可以當字典的 key;串列則不行:
1
2
3
4
5
6
7
8
| locations = {
(25.0478, 121.5319): "台北車站",
(22.6273, 120.3014): "高雄車站",
}
print(locations[(25.0478, 121.5319)]) # 台北車站
# 以下會報錯
# bad = {[1, 2]: "value"} # ❌ TypeError: unhashable type: 'list'
|
記憶體效率#
元組比串列佔用 更少記憶體 ,迭代速度也略快:
1
2
3
4
5
6
7
| import sys
lst = [1, 2, 3, 4, 5]
tup = (1, 2, 3, 4, 5)
print(sys.getsizeof(lst)) # 88(bytes,較多)
print(sys.getsizeof(tup)) # 72(bytes,較少)
|
常用技巧#
元組轉串列、串列轉元組#
1
2
3
4
5
| t = (1, 2, 3)
lst = list(t) # 轉成串列(可修改)
lst.append(4)
t2 = tuple(lst) # 再轉回元組
print(t2) # (1, 2, 3, 4)
|
用 zip() 建立元組串列#
1
2
3
4
5
6
7
8
| names = ["Alice", "Bob", "Charlie"]
scores = [85, 92, 78]
pairs = list(zip(names, scores))
print(pairs) # [('Alice', 85), ('Bob', 92), ('Charlie', 78)]
for name, score in pairs:
print(f"{name}:{score} 分")
|
具名元組(namedtuple)#
當元組欄位較多時,可用 namedtuple 讓程式碼更易讀:
1
2
3
4
5
6
7
8
| from collections import namedtuple
Point = namedtuple("Point", ["x", "y"])
p = Point(3, 4)
print(p.x, p.y) # 3 4(可用名稱存取)
print(p[0], p[1]) # 3 4(也可用索引)
print(p) # Point(x=3, y=4)
|