一起玩Python程式:新手寫程式也可以這麼簡單!

資料容器(下) - 字典(Dictionary)

張傑帆

National Taiwan University

資料容器(下)

目錄

  1. 字典(Dictionary)基礎概念與語法
  2. 字典的鍵值配對操作
  3. 字典的新增、刪除、修改方法 (keys, values, items)
  4. 設計物品屬性結構 (名稱、類型、數量、價值)
  5. 建立物品分類與數量管理系統
  6. 作業

Alt1

🎯 學習目標

今天我們要打造一個神奇遊戲背包系統!
就像RPG遊戲中的道具欄一樣,我們需要:
✨ 管理各種物品的名稱、類型、數量
🔍 快速搜尋特定物品
📊 分類整理背包內容
⚖️ 控制背包容量限制

準備好成為程式背包大師了嗎?

Let's code! 🎮💎

🗝️ 字典 - 神秘的鍵值寶盒

想像一下,你有一個神奇的收納盒:
d = {key1: value1, key2: value2}

  • 每個格子都有標籤(鍵 Key)
  • 每個標籤對應一個物品(值 Value)
  • 你可以透過標籤快速找到物品!
# 創建你的第一個背包字典
backpack = {
  "長劍": 1,
  "治療藥水": 5,
  "魔法書": 2
}

print(f"背包內容:{backpack}")
print(f"治療藥水數量:{backpack['治療藥水']}")

字典語法大解密 🔐

操作 語法 說明
創建 dict = {} 空字典
取值 dict[key] 獲取對應值
賦值 dict[key] = value 新增或修改
刪除 del dict[key] 刪除鍵值對(pair)
# 實用範例
player_stats = {
  "生命值": 100,
  "魔力值": 50,
  "等級": 15
}

小練習1 - 建立你的英雄資料

創建一個字典來記錄你的遊戲角色:

# 請完成這個字典
hero = {
  "姓名": "你的英雄名",
  "職業": "戰士/法師/盜賊",
  "等級": 1,
  "經驗值": 0
}

# 練習:印出英雄的職業和等級
print(f"職業:{hero['職業']}")
print(f"等級:{hero['等級']}")

挑戰1:新增一個"技能"鍵(key),值(value)為技能列表!
挑戰2:將該技能列表印出來!

🎒 進階背包系統 - 物品屬性管理

# 複雜物品結構
items = {
  "炎之劍": {
    "類型": "武器",
    "攻擊力": 50,
    "數量": 1,
    "價值": 1000,
    "稀有度": "史詩"
  },
  "生命藥水": {
    "類型": "消耗品",
    "效果": "恢復50HP",
    "數量": 10,
    "價值": 50
  }
}

# 查看物品詳情
sword = items["炎之劍"]
print(f"武器攻擊力:{sword['攻擊力']}")

字典方法大全 🛠️

backpack = {"劍": 1, "盾": 1, "藥水": 5}

# 重要方法
keys = backpack.keys()      # 所有鍵
values = backpack.values()  # 所有值
items = backpack.items()    # 所有鍵值對

# 安全取值
count = backpack.get("弓箭", 0)  # 不存在返回0

# 更新字典
new_items = {"弓箭": 1, "箭矢": 50}
backpack.update(new_items)

字典的增刪查改範例

# 增加新鍵值對
backpack["弓箭"] = 2
print(backpack)  # {'長劍': 1, '治療藥水': 5, '魔法書': 2, '弓箭': 2}

# 查詢某個鍵的值
print(backpack.get("魔法書"))  # 2
print(backpack.get("盾牌", "沒有此物品"))  # 沒有此物品

# 修改現有鍵的值
backpack["治療藥水"] = 10
print(backpack["治療藥水"])  # 10

# 刪除鍵值對
del backpack["長劍"]
print(backpack)  # {'治療藥水': 10, '魔法書': 2, '弓箭': 2}

# 使用 pop() 刪除並取得值
removed = backpack.pop("弓箭", None)
print(f"移除弓箭,數量:{removed}")  # 移除弓箭,數量:2
print(backpack)  # {'治療藥水': 10, '魔法書': 2}

小練習2 - 更新你的英雄資料

創建一個字典來記錄你的遊戲角色:
在字典建立後不改動原文的情況下,完成以下任務:

  1. 將等級提升到5
  2. 新增一個"技能"鍵(key),值(value)為技能列表
  3. 將該技能列表(List)印出來

hero = {
  "姓名": "你的英雄名",
  "職業": "戰士/法師/盜賊",
  "等級": 1,
  "經驗值": 0
}

小練習 3 - 背包管理系統

backpack = {}
while True:
  item = input("請輸入要新增的物品名稱(或輸入 q 結束):")
  if item == "q":
    break
  qty = int(input(f"請輸入 {item} 的數量:"))
  ... # 在此處新增物品到背包
  print(f"已新增 {qty}{item}")

print("=== 背包內容 ===")
for item, count in backpack.items():
  print(f"{item}: {count}")

休息時間 ☕

使用dict與list有何不同?

特性 list (串列) dict (字典)
資料存取方式 依照索引 (整數) 依照鍵 (key)
資料結構 有序、可重複 無序(Python 3.7+有插入順序)、鍵唯一
用途 儲存一組有順序的資料 儲存一組有對應關係的資料(鍵值對)
查找效率 O(n)(需遍歷) O(1)(直接透過key查找)
範例 lst = [10, 20, 30] d = {"蘋果": 5, "香蕉": 3}

結論

  • 當你需要依照順序或位置存取資料,用list。
  • 當你需要根據名稱或標籤快速查找資料,用dict。

dict可以做到O(1)的原理

為什麼dict查找是O(1)?

Python 的 dict(字典)底層是Hash Table實作。

  • 每個鍵(key)經過 hash 函數轉換成一個數字(hash值)。
  • 這個 hash 值決定了資料在記憶體中的存放位置。
  • 查找時,直接根據 hash 值定位,不需遍歷所有元素。

優點:

  • 查找、插入、刪除的平均時間複雜度都是 O(1)。
  • 只要鍵的 hash 值不衝突(碰撞),效率非常高。

這也是為什麼 dict 適合用來做大量資料的快速查找!

🎮 實戰項目:RPG背包系統

請設計一個「背包管理系統」
讓使用者可以:

  1. 新增道具及數量
  2. 查詢某個道具的數量
  3. 修改道具的數量
  4. 刪除某個道具

並設計互動式選單讓使用者操作!

backpack = {}

while True:
  print("\n=== 背包管理系統 ===")
  print("1. 新增道具及數量")
  print("2. 查詢某個道具的數量")
  print("3. 修改道具的數量")
  print("4. 刪除某個道具")
  print("5. 顯示所有道具")
  print("0. 離開")
  choice = input("請輸入選項:")

  if choice == "1":
    name = input("請輸入道具名稱:")
    qty = int(input("請輸入數量:"))
    if name in backpack:
      backpack[name] += qty
    else:
      backpack[name] = qty
    print(f"已新增 {qty}{name}")

(接下頁)

  elif choice == "2":
    name = input("請輸入要查詢的道具名稱:")
    print(f"{name} 數量:{backpack.get(name, 0)}")

  elif choice == "3":
    name = input("請輸入要修改的道具名稱:")
    if name in backpack:
      qty = int(input("請輸入新的數量:"))
      backpack[name] = qty
      print(f"{name} 數量已修改為 {qty}")
    else:
      print("背包中沒有此道具")

(接下頁)


  elif choice == "4":
    name = input("請輸入要刪除的道具名稱:")
    if name in backpack:
      del backpack[name]
      print(f"{name} 已刪除")
    else:
      print("背包中沒有此道具")

  elif choice == "5":
    print("=== 背包內容 ===")
    for item, qty in backpack.items():
      print(f"{item}: {qty}")

  elif choice == "0":
    print("離開背包管理系統")
    break

  else:
    print("請輸入有效選項")

🧠 運算思維總整理

抽象化:將現實世界的背包概念抽象為鍵值對結構

  • 物品名稱 → 鍵(Key)
  • 物品資訊 → 值(Value)

模式識別:識別適合使用字典的場景

  • 需要快速查找的資料
  • 有明確對應關係的資料

演算法思維:設計高效的資料管理邏輯

  • 較少時間複雜度的查找
  • 動態新增刪除物品

本週總結 🎉

🎒 字典是什麼?

  • 鍵值對的資料結構
  • 快速查找和管理資料

🔧 核心方法

  • keys(), values(), items()
  • get(), update(), del

🎮 實際應用

  • 遊戲背包系統
  • 資料庫般的資料管理

作業:打造你的資料系統 📝

📝 選項一:基礎練習 (適合初學者)

創建一個簡單的魔法道具管理系統:

要求:

  1. 新增道具及數量
  2. 查詢道具數量
  3. 修改道具數量
  4. 刪除道具

🔧 選項二:進階應用 (有點挑戰性)

設計一個餐廳點餐系統:

  • 菜單字典(菜名、價格、類別)
  • 訂單管理功能
  • 計算總金額
  • 按類別分類菜品

挑戰:加入會員折扣機制!

🚀 選項三:創意發揮 (自由度高)

設計你自己的管理系統:

  • 圖書館借閱系統
  • 寵物資料管理
  • 社團成員資料庫

發揮創意,展現你的程式魔法! 🌟

補充資料 - Set(集合)

Set 是 Python 中用來儲存不重複元素的資料結構,常用於去除重複、集合運算。

基本語法

s = {1, 2, 3, 2}
print(s)        # {1, 2, 3}
s.add(4)        # 新增元素
s.remove(2)     # 移除元素
  • 用大括號 {} 建立
  • 元素不可重複、無順序
  • 支援集合運算:交集、聯集、差集

常用方法

說明 方法 代表符號
新增元素 x add(x)
移除元素 x remove(x)
聯集 union(s2) |
交集 intersection(s2) &
差集 difference(s2) -
互異(對稱差集) symmetric_difference(s2) ^
是否為子集合 issubset(s2) <=
是否為超集合 issuperset(s2) >=

範例:集合運算

a = {1, 2, 3}
b = {3, 4, 5}

print(a | b)    # 聯集 {1, 2, 3, 4, 5}
print(a & b)    # 交集 {3}
print(a - b)    # 差集 {1, 2}
print(a ^ b)    # 互異 {1, 2, 4, 5}

適合用於:

  • 去除重複資料
  • 比較、合併多組資料
  • 數學集合相關運算

超集合與子集合

superset_a = {1, 2, 3, 4, 5}
subset_b = {2, 3}
subset_c = {6, 7}

print(f"集合 A: {superset_a}")
print(f"集合 B: {subset_b}")
print(f"集合 C: {subset_c}")
print(f"B 是 A 的子集合嗎? {subset_b <= superset_a}")  # True
print(f"A 是 B 的超集合嗎? {superset_a >= subset_b}")  # True
print(f"C 是 A 的子集合嗎? {subset_c <= superset_a}")  # False
print(f"A 是 C 的超集合嗎? {superset_a >= subset_c}")  # False

補充資料 - Tuple(元組)

Tuple 是 Python 中一種不可變的序列型資料結構,常用來儲存一組不需修改的資料。

基本語法

t = (10, 20, 30)
print(t[0])      # 10
print(len(t))    # 3
  • 用小括號 () 建立
  • 元素可為不同型別
  • 不可修改(不能增刪改)

什麼時候用 Tuple?

  • 資料不需更動時(如座標、設定值)
  • 作為函式回傳多個值 (後面才會教)

與 List 差異

特性 List(串列) Tuple(元組)
可變性 可修改 不可修改
語法 [] ()
用途 動態資料 固定資料

-----------------------------------------

圖片放大特效

table樣式

![Alt1](../images/1200px-National_Taiwan_University_logo.svg.png)![Alt2](../images/Python-logo-notext.svg.png) <style scoped> img[alt="Alt1"]{ background: rgba(255, 255, 255, 0); position: absolute; top: 10%; left: 10%; /* transform: translate(-50%, -50%); */ width: 200px; /* 調整圖片寬度 */ height: auto; /* 保持原始比例 */ padding:0; margin:0; z-index: 1; } img[alt="Alt2"]{ background: rgba(255, 255, 255, 0); position: absolute; top: 10%; left: 75%; /* transform: translate(-50%, -50%); */ width: 200px; /* 調整圖片寬度 */ height: auto; /* 保持原始比例 */ padding:0; margin:0; z-index: 2; } </style>

hero["技能"] = ["揮砍", "火球術", "潛行"]

真正的背包系統需要更詳細的物品資訊:

"技能": ["揮砍", "火球術", "潛行"],

實作一個簡單的背包管理功能:

```python backpack = {} while True: item = input("請輸入要新增的物品名稱(或輸入 q 結束):") if item == "q": break qty = int(input(f"請輸入 {item} 的數量:")) if item in backpack: backpack[item] += qty else: backpack[item] = qty print(f"已新增 {qty} 個 {item}") print("=== 背包內容 ===") for item, count in backpack.items(): print(f"{item}: {count}") ``` ```python def add_item(backpack, item_name, quantity): """新增物品到背包""" if item_name in backpack: backpack[item_name] += quantity else: backpack[item_name] = quantity print(f"已新增 {quantity} 個 {item_name}") def show_backpack(backpack): """顯示背包內容""" print("=== 背包內容 ===") for item, count in backpack.items(): print(f"{item}: {count}") # 測試你的函數 my_backpack = {} add_item(my_backpack, "治療藥水", 3) show_backpack(my_backpack) ```

### 差異比較

**注意:** - 若發生 hash 碰撞,dict 會用開放定址法等方式處理,極端情況下效率會降低,但平均仍為 O(1)。

```python class GameBackpack: def __init__(self, max_capacity=20): self.items = {} self.max_capacity = max_capacity def add_item(self, name, item_data): current_total = sum(self.items.values()) if current_total >= self.max_capacity: return "背包已滿!" if name in self.items: self.items[name]["數量"] += item_data["數量"] else: self.items[name] = item_data return f"成功添加 {name}" def get_items_by_type(self, item_type): return {k: v for k, v in self.items.items() if v["類型"] == item_type} ```

--- ### 範例:函式回傳多值 ```python def get_position(): x, y = 5, 8 return (x, y) pos = get_position() print(pos) # (5, 8) ```