元組、集合、字典
除了串列,Python 還有三種常用的資料結構:元組、集合、字典。它們各有適合的場合。
元組 Tuple
Section titled “元組 Tuple”元組很像串列,一樣是一排有順序的資料,但改用小括號 (),而且建立之後就不能再改。索引、切片、負索引、len() 這些用法都和串列一樣:
point = (3, 5)
print(point[0])print(point[1])
x, y = pointprint(x, y)最後兩行是拆解:x, y = point 一口氣把元組裡的兩個值分別指定給 x 和 y,很常用來一次拿出好幾個值。
只有一個元素的元組要特別小心:元素後面一定要加逗號。少了逗號,(1) 只是「用括號括起來的 1」,型別還是整數,不是元組:
# ruff 平常會把多餘的括號拿掉,(1) 會變成 1;這行用 fmt: skip 保留原樣,才示範得出陷阱。a = (1) # fmt: skipprint(a, type(a))
b = (1,)print(b, type(b))元組不能改,但還是可以用 count() 和 index(),用法和串列一樣。想加東西可以用 +=,不過它是做出一個新的元組,不是改原本的那個;串列的 append() 才是直接改原本的:
scores = (85, 90, 85, 78)
print(scores.count(85))print(scores.index(90))
scores += (100,)print(scores)需要一組固定、不希望被改到的資料(例如一個座標、一組設定)時,就用元組。
集合 Set
Section titled “集合 Set”集合用大括號 {},特點是不重複而且沒有順序。把一堆值丟進集合,重複的會自動被去掉:
numbers = {3, 1, 4, 1, 5, 9, 2, 6}
print(numbers)print(len(numbers))因為沒有順序,印出來的排列不保證跟你寫的一樣,也不能用索引取值。它最適合拿來「去除重複」或「檢查某個東西在不在」。
集合還能做數學上的交集、聯集、差集、對稱差集。把兩個集合想成兩個圓,每個運算就是選出其中一塊(藍色的部分):
a & b交集a | b聯集a - b差集a ^ b對稱差集對照圖上的藍色範圍,實際跑一次就很清楚:
a = {1, 2, 3, 4}b = {3, 4, 5, 6}
print(a & b)print(a | b)print(a - b)print(a ^ b)a & b:交集,兩邊都有的(兩圓重疊的中間)。a | b:聯集,兩邊合起來(兩圓的全部,一樣不重複)。a - b:差集,在a但不在b的(左圓扣掉重疊)。a ^ b:對稱差集,只在其中一邊出現的(兩圓各自的部分,中間重疊反而不算)。
上面那四個運算也有對應的方法寫法,|、&、-、^ 分別就是 union、intersection、difference、symmetric_difference,做的事一模一樣:
a = {1, 2, 3}b = {3, 4, 5}
print(a.union(b))print(a.intersection(b))print(a.difference(b))print(a.symmetric_difference(b))union(b):聯集,和a | b一樣。intersection(b):交集,和a & b一樣。difference(b):差集,和a - b一樣。symmetric_difference(b):對稱差集,和a ^ b一樣。
集合本身可以改,所以也能單獨加、拿掉元素,或整個清空:
a = {1, 2, 3}
a.add(6)print(a)
a.remove(3)print(a)
a.clear()print(a)add(x):加一個元素進去。remove(x):拿掉某個元素(x不在裡面會出錯)。clear():清空整個集合。
還有兩個方法用來檢查「包含關係」,回傳 True 或 False。issubset 問「我被對方包住嗎」,issuperset 反過來問「我把對方包住嗎」,是同一件事的兩面。畫成圖就是看誰在誰裡面:
a ⊆ b子集合a ⊇ b超集合跑一次就會看到,{1, 2}.issubset(a) 和 a.issuperset({1, 2}) 問的是同一件事,所以都是 True:
a = {1, 2, 3}
print({1, 2}.issubset(a))print(a.issuperset({1, 2}))print({1, 5}.issubset(a))issubset(b):檢查自己是不是b的子集合,也就是「自己的每個元素都在b裡」,是就回傳True。issuperset(b):反過來,檢查自己是不是b的超集合,也就是「b的每個元素都在自己裡」。
字典 Dictionary
Section titled “字典 Dictionary”字典用「鍵(key)對應值(value)」的方式存資料,寫成 {鍵: 值}。不像串列用數字索引,字典是用鍵來取值:
student = {"name": "小明", "age": 18}
print(student["name"])print(student["age"])
print("name" in student)print("score" in student)用 in 可以檢查某個鍵在不在字典裡,回傳 True 或 False;查的是鍵,不是值。
用 字典[鍵] = 值 可以改掉某個鍵的值,如果那個鍵還不存在,就會新增一組。想一次改好幾個鍵,用 update() 更省事,把另一個字典傳進去,重複的鍵換成新值、沒有的鍵加進去:
student = {"name": "小明", "age": 18}
student["age"] = 19student["city"] = "台北"print(student)
student.update({"age": 20, "phone": "0912"})print(student)用 for 走過字典,每一圈拿到的是鍵,再用 字典[鍵] 就能拿到對應的值:
scores = {"數學": 90, "英文": 85, "國文": 78}
for subject in scores: print(subject, ":", scores[subject])如果想一次拿到鍵和值,用 items() 更方便,它每一圈同時給你兩個。另外 get(鍵) 是比較安全的取值方式。那個鍵不存在時,字典[鍵] 會直接出錯,get() 則回傳 None,還能指定找不到時要用的預設值:
scores = {"數學": 90, "英文": 85}
for subject, score in scores.items(): print(subject, score)
print(scores.get("數學"))print(scores.get("物理", 0))想單獨拿所有的鍵或所有的值,可以用 keys() 和 values():
scores = {"數學": 90, "英文": 85}
print(list(scores.keys()))print(list(scores.values()))想刪掉字典裡的東西,有三種做法:
student = {"name": "小明", "age": 18, "city": "台北"}
del student["city"]print(student)
age = student.pop("age")print(age)print(student)
student.clear()print(student)del 字典[鍵]:刪掉指定的那一組。pop(鍵):刪掉那一組,同時把值回傳給你。clear():清空整個字典。
字典也有 .copy(),是淺複製;要連裡層一起複製,得用 copy 模組的 deepcopy,規則和串列那章完全一樣。
字典很適合表示「一筆有很多欄位的資料」,例如一個學生有姓名、年齡、住哪裡;或是一組對應關係,例如每一科對應一個分數。
list()、set()、tuple() 可以把其他的資料轉成串列、集合、元組。這在實務上很常用,例如用 set() 幫串列快速去除重複,或用 list() 把字串拆成一個個字元:
text = "hello"
print(list(text))print(set(text))print(tuple([1, 2, 3]))v0.4.0 (148a67b)