回文章列表
Python8 分鐘閱讀2026年6月7日

用 Python 字典做一個商品管理程式(while 選單 + CRUD 實戰)

#Python#字典#dict#實戰

文章目錄

如果你已經學過 dict 的基本操作——d[key] = value 存資料、for k, v in d.items() 走訪、in 判斷 key 存不存在——大概會有一個疑問:這些零散的操作要怎麼兜成一支「真正的程式」?

實務上答案很單純:套一個 while True 選單,把 dict 的增刪改查各包成一個選項,使用者輸入數字選功能,程式就一直跑到使用者選擇離開為止。這篇就帶你寫一支完整的「水果商品管理程式」,把 dict 的 CRUD(新增 Create、查詢 Read、修改 Update、刪除 Delete)全部串起來。

先看完整程式長什麼樣子

這支程式用一個 fruitPrices 字典存商品名稱和價格,選單有五個選項:

fruitPrices = {}
while True:
    print('{:*^20}'.format('水果商品管理程式'))
    print('{:^20}'.format('(1).新增產品'))
    print('{:^20}'.format('(2).刪除產品'))
    print('{:^20}'.format('(3).修改產品'))
    print('{:^20}'.format('(4).目前產品'))
    print('{:^20}'.format('(5).離開'))
    choice = int(input('請輸入功能選項:'))
    if choice == 5:
        print('離開程式')
        break
    elif choice == 1:                       # 新增
        item = input('請輸入新產品:')
        if item in fruitPrices:
            print('已有該商品!')
        else:
            price = input(f'請輸入 {item} 價格:')
            fruitPrices[item] = price
            print(f'產品 {item} 新增完成!')
    elif choice == 2:                       # 刪除
        item = input('請輸入刪除產品:')
        if item not in fruitPrices:
            print('無該商品')
        else:
            del fruitPrices[item]
            print(f'產品 {item} 刪除完成!')
    elif choice == 3:                       # 修改
        item = input('請輸入修改產品:')
        if item not in fruitPrices:
            print('無該商品')
        else:
            fruitPrices[item] = input(f'請輸入 {item} 價格:')
            print(f'產品 {item} 修改完成!')
    elif choice == 4:                       # 目前產品
        print('目前產品:')
        for key, value in fruitPrices.items():
            print(f'{key}={value}', end=' ')
        print()

先不急著逐行看,我們一段一段拆開講。

第一步:選單骨架,先把「離開」寫對

任何選單程式的骨架都長這樣:while True 讓程式不斷重複印選單、讀輸入,只有輸入符合離開條件時才 break 跳出迴圈。

fruitPrices = {}
while True:
    print('{:*^20}'.format('水果商品管理程式'))
    print('{:^20}'.format('(1).新增產品'))
    print('{:^20}'.format('(2).刪除產品'))
    print('{:^20}'.format('(3).修改產品'))
    print('{:^20}'.format('(4).目前產品'))
    print('{:^20}'.format('(5).離開'))
    choice = int(input('請輸入功能選項:'))
    if choice == 5:
        print('離開程式')
        break

這裡有兩個 str.format() 的置中用法值得看一下:

  • '{:*^20}'.format('水果商品管理程式'):^ 是置中對齊,20 是總寬度,* 是補在兩側的填充字元。跑出來會是 ******水果商品管理程式******(星號補滿兩側湊到 20 個字元寬)。
  • '{:^20}'.format('(1).新增產品'):同樣是置中,但沒指定填充字元,預設用空白補,讓每個選項看起來左右對齊、排版工整。

先把這段單獨跑起來,你會看到選單一直重複印,直到輸入 5 才會印出「離開程式」然後結束。這一步先確定選單骨架沒問題,之後加其他功能才不會混在一起除錯。

第二步:新增與刪除——in / not in 用法剛好相反

接下來把「新增」「刪除」接在 choice == 5 判斷式之後,用 elif 串起來:

    elif choice == 1:                       # 新增
        item = input('請輸入新產品:')
        if item in fruitPrices:
            print('已有該商品!')
        else:
            price = input(f'請輸入 {item} 價格:')
            fruitPrices[item] = price
            print(f'產品 {item} 新增完成!')
    elif choice == 2:                       # 刪除
        item = input('請輸入刪除產品:')
        if item not in fruitPrices:
            print('無該商品')
        else:
            del fruitPrices[item]
            print(f'產品 {item} 刪除完成!')

這段是整支程式最該記住的地方:新增前檢查「已存在」,刪除前檢查「不存在」,方向剛好相反。

  • 新增的邏輯是「不能加進已經有的東西」,所以用 if item in fruitPrices 擋掉重複新增。
  • 刪除的邏輯是「不能刪不存在的東西」,所以用 if item not in fruitPrices 擋掉刪除失敗。

in 和 not in 對 dict 做的事情,是拿左邊的值去比對 dict 所有的 key(不會比對 value)。item in fruitPrices 等於在問「item 是不是 fruitPrices 的某個 key」。

真正執行刪除動作的是 del fruitPrices[item]——del 是 Python 的關鍵字,作用是把整個 key-value pair 從字典裡移除,不是只把 value 清空。而新增動作反過來很單純,直接賦值即可:fruitPrices[item] = price,如果這個 key 原本不存在,Python 會自動幫你建立。

第三步:修改與查詢——一個是「有條件的賦值」,一個是走訪

    elif choice == 3:                       # 修改
        item = input('請輸入修改產品:')
        if item not in fruitPrices:
            print('無該商品')
        else:
            fruitPrices[item] = input(f'請輸入 {item} 價格:')
            print(f'產品 {item} 修改完成!')
    elif choice == 4:                       # 目前產品
        print('目前產品:')
        for key, value in fruitPrices.items():
            print(f'{key}={value}', end=' ')
        print()

「修改」跟「刪除」用同一種存在性檢查(not in,因為不能改一個不存在的商品),但真正動手的方式跟「新增」一樣,都是 fruitPrices[item] = 新值。這其實透露一個重點:Python 的 dict 沒有分開的「新增」和「修改」指令,dict[key] = value 這一行,key 不存在時是新增、key 存在時就是修改,差別只在於程式邏輯要不要先用 in/not in 攔一層。

「目前產品」則是單純走訪整個字典:fruitPrices.items() 會把每一組 key-value 拆成 (key, value) 的組合讓 for 迴圈取用,所以能寫成 for key, value in fruitPrices.items()。這裡用 print(f'{key}={value}', end=' ') 讓每個商品印在同一行、用空白隔開,迴圈跑完之後再補一個空的 print() 換行,不然下一輪選單會緊接在商品清單後面,看起來很擠。

dict[key] 與 .get() 的差別

fruitPrices = {"蘋果": "30"}
print(fruitPrices.get("香蕉", "無該商品"))
print(fruitPrices["香蕉"])

執行結果:

無該商品
Traceback (most recent call last):
  File "C:\demo\demo.py", line 3, in <module>
    print(fruitPrices["香蕉"])
          ~~~~~~~~~~~^^^^^^^^
KeyError: '香蕉'

![執行結果:.get() 查不到回傳預設值;用 [] 查不到會 KeyError](/blog/python-dict-product-manager/keyerror.png)

dict[key] 查不到會直接丟 KeyError(而且錯誤訊息只有 key 本身 '香蕉');.get(key, 預設值) 則溫和地回傳預設值。要用哪個取決於「查不到是正常情況還是 bug」:使用者查詢商品——正常,用 get 或 in;程式內部保證一定存在的設定——用 [],出錯就該大聲報。(Python 3.11 之後的錯誤訊息會多出 ~~~^^^ 標示錯誤位置,舊版沒有,版本不同箭頭符號會略有差異。)

合併起來跑一次

把三段接在一起就是文章開頭那支完整程式。實際操作一輪:先新增蘋果 30 元、香蕉 20 元,再查看目前產品,最後離開:

******水果商品管理程式******
      (1).新增產品      
      (2).刪除產品      
      (3).修改產品      
      (4).目前產品      
      (5).離開         
請輸入功能選項:1
請輸入新產品:蘋果
請輸入 蘋果 價格:30
產品 蘋果 新增完成!
******水果商品管理程式******
      (1).新增產品      
      (2).刪除產品      
      (3).修改產品      
      (4).目前產品      
      (5).離開         
請輸入功能選項:1
請輸入新產品:香蕉
請輸入 香蕉 價格:20
產品 香蕉 新增完成!
******水果商品管理程式******
      (1).新增產品      
      (2).刪除產品      
      (3).修改產品      
      (4).目前產品      
      (5).離開         
請輸入功能選項:4
目前產品:
蘋果=30 香蕉=20 
******水果商品管理程式******
      (1).新增產品      
      (2).刪除產品      
      (3).修改產品      
      (4).目前產品      
      (5).離開         
請輸入功能選項:5
離開程式

商品順序照新增順序排列(蘋果先加,所以先印),這是 Python 3.7 之後 dict 保留插入順序的特性,不是巧合。

實跑:新增、重複新增、列出、離開

為了讓讀者能自己驗證,這裡把課堂用的版本精簡成只保留新增/目前產品/離開(邏輯相同),並以預先準備好的輸入實跑。輸入順序:1→蘋果→30→1→蘋果(重複)→4→5。由於輸入以管線餵入,終端不會顯示打的字,請對照輸入順序閱讀:

fruitPrices = {}
while True:
    print('{:*^20}'.format('水果商品管理程式'))
    print('(1).新增產品  (4).目前產品  (5).離開')
    choice = int(input('請輸入功能選項:'))
    if choice == 5:
        print('離開程式')
        break
    elif choice == 1:
        item = input('請輸入新產品:')
        if item in fruitPrices:
            print('已有該商品!')
        else:
            price = input(f'請輸入 {item} 價格:')
            fruitPrices[item] = price
            print(f'產品 {item} 新增完成!')
    elif choice == 4:
        print('目前產品:')
        for key, value in fruitPrices.items():
            print(f'{key}={value}', end=' ')
        print()

執行結果:

******水果商品管理程式******
(1).新增產品  (4).目前產品  (5).離開
請輸入功能選項:請輸入新產品:請輸入 蘋果 價格:產品 蘋果 新增完成!
******水果商品管理程式******
(1).新增產品  (4).目前產品  (5).離開
請輸入功能選項:請輸入新產品:已有該商品!
******水果商品管理程式******
(1).新增產品  (4).目前產品  (5).離開
請輸入功能選項:目前產品:
蘋果=30
******水果商品管理程式******
(1).新增產品  (4).目前產品  (5).離開
請輸入功能選項:離開程式
執行結果:商品管理選單:新增蘋果、重複新增被擋下、列出、離開
執行結果:商品管理選單:新增蘋果、重複新增被擋下、列出、離開

第二次新增蘋果時,程式印出「已有該商品!」並沒有覆蓋價格——這就是 if item in fruitPrices 的守門效果。

學生做這個作業最常見的四個錯

學生做這支選單/CRUD 小作業,我看過最常見的錯有四種,你自己寫完之後可以對照檢查:

1. 判斷輸入選項時,數字 1 和字串 "1" 搞混。 input() 拿到的是字串,沒轉型就拿去和數字 1 比,永遠不相等,選單怎麼選都沒反應。 2. 忘記先寫離開的邏輯。 選單是 while True,如果沒先把「離開」寫對,程式就很難停下來(第一步先寫離開,就是為了避免這件事)。 3. 例外處理沒用好,只要輸入錯誤,程式就崩潰。 下一段會實際看一次。 4. 無法連續輸入品項。 新增完一個商品就結束,沒辦法一次輸入好幾個,通常是迴圈放錯位置。

一個常見的坑:選單輸入打錯字會直接崩潰

試著在「請輸入功能選項:」故意打一個中文字或英文字看看,例如輸入 abc,你會看到程式直接丟出 ValueError: invalid literal for int() with base 10: 'abc' 然後整支程式當掉。

原因在這一行:

choice = int(input('請輸入功能選項:'))

input() 拿到的永遠是字串,int() 硬把它轉成整數;只要字串裡不是純數字,int() 轉換失敗就會丟出 ValueError,而這支程式沒有做任何攔截,例外會一路往外拋,直接中止整個程式。

真正上線的程式通常會加一層 try/except 或先用 str.isdigit() 檢查再轉換,把這個崩潰點補起來。這篇先把 dict 的 CRUD 邏輯講清楚,所以前面的版本是刻意簡化的;等邏輯都通了,下面會示範一個最小的防呆做法,把這個崩潰點補起來。

「輸入錯誤就崩潰」是這類作業很常見的一關,下面先看崩潰現場,再看最小的修法。

崩潰現場:已經輸入的商品全部消失

輸入順序:1→蘋果→30→abc。

******水果商品管理程式******
(1).新增產品  (4).目前產品  (5).離開
請輸入功能選項:請輸入新產品:請輸入 蘋果 價格:產品 蘋果 新增完成!
******水果商品管理程式******
(1).新增產品  (4).目前產品  (5).離開
請輸入功能選項:Traceback (most recent call last):
  File "C:\demo\demo.py", line 5, in <module>
    choice = int(input('請輸入功能選項:'))
             ~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: invalid literal for int() with base 10: 'abc'
執行結果:在選單打 abc:ValueError 讓程式中斷,剛新增的蘋果只存在記憶體,直接消失
執行結果:在選單打 abc:ValueError 讓程式中斷,剛新增的蘋果只存在記憶體,直接消失

這裡有一個比錯誤訊息更重要的觀察:這支程式的資料只存在變數 fruitPrices 裡,程式一崩潰,剛輸入的商品就全部消失。所以防呆不只是「好看」,而是在保護使用者辛苦輸入的資料。(Python 3.11 之後的錯誤訊息會多出 ~~~^^^ 標示錯誤位置,舊版沒有,版本不同箭頭符號會略有差異。)

修正:替換選項轉型的區塊,改成 try/except + continue

fruitPrices = {}
while True:
    print('{:*^20}'.format('水果商品管理程式'))
    print('(1).新增產品  (4).目前產品  (5).離開')
    try:
        choice = int(input('請輸入功能選項:'))
    except ValueError:
        print('請輸入數字 1~5')
        continue
    if choice == 5:
        print('離開程式')
        break
    elif choice == 1:
        item = input('請輸入新產品:')
        if item in fruitPrices:
            print('已有該商品!')
        else:
            price = input(f'請輸入 {item} 價格:')
            fruitPrices[item] = price
            print(f'產品 {item} 新增完成!')
    elif choice == 4:
        print('目前產品:')
        for key, value in fruitPrices.items():
            print(f'{key}={value}', end=' ')
        print()

同樣的輸入順序(1→蘋果→30→abc→4→5),執行結果:

******水果商品管理程式******
(1).新增產品  (4).目前產品  (5).離開
請輸入功能選項:請輸入新產品:請輸入 蘋果 價格:產品 蘋果 新增完成!
******水果商品管理程式******
(1).新增產品  (4).目前產品  (5).離開
請輸入功能選項:請輸入數字 1~5
******水果商品管理程式******
(1).新增產品  (4).目前產品  (5).離開
請輸入功能選項:目前產品:
蘋果=30
******水果商品管理程式******
(1).新增產品  (4).目前產品  (5).離開
請輸入功能選項:離開程式
執行結果:補上 try/except 後,打 abc 只會被請回選單,蘋果還在
執行結果:補上 try/except 後,打 abc 只會被請回選單,蘋果還在

打了 abc 只被提示「請輸入數字 1~5」,回到選單後 4 依然能列出先前新增的蘋果。continue 是關鍵:它讓迴圈直接跳回下一輪,而不是往下走到 choice 尚未被賦值的分支。

資料沒了、程式也沒存:我的兩個習慣

說到「存檔」,還有一個很實際的習慣想提醒:程式本身就是文字檔的一種,輸入了很多內容卻忘了儲存,一當機就白費。所以我的習慣是寫完一個段落就執行一次程式;在編輯器有開啟「執行前自動儲存」(例如 VS Code 的相關設定)時,執行也會順便存檔,但不要完全依賴,仍然要適時按快捷鍵 Ctrl+S。

要特別分清楚:這是在保護「程式碼」。前面崩潰時消失的「商品資料」只存在變數裡,跑一次程式並不會讓它持久保存;要保留商品資料,得另外把資料寫進檔案或資料庫,這正是下面延伸路線的起點。

做完之後,學生接著想做什麼

這個作業做完,學生通常會沿著一條路線往下走:

1. 學到存檔,就會把這支管理程式改成有儲存和讀取功能,不再一關掉資料就沒了。 2. 學會資料庫之後,開始用資料庫的思維去設計資料表,資料更安全,查詢也更快。 3. 學會 tkinter 之後,就會希望把程式做成 GUI 介面,把資料庫、爬蟲結合起來,讓整個使用體驗更完整。

小結

整支程式其實就是一句話:dict 的 CRUD 操作,外面套一層 while True 選單。新增前用 in 擋重複、刪除和修改前用 not in 擋不存在,兩個方向剛好相反;del dict[key] 負責刪、直接賦值 dict[key] = 值 兼職新增和修改、.items() 負責走訪印出全部內容。這四個操作組合起來,幾乎就是任何一支「用字典存資料的小型管理程式」的骨架,換成學生成績、書籍庫存、會員資料,套路都一樣。

如果你還沒有練過 dict 的基本操作,可以先回頭複習變數、流程控制與資料型態,再回來對照這支程式會更清楚每一行在做什麼。

相關課程

Python 基礎入門

從零開始學習 Python 程式語言,掌握變數、流程控制、函式與模組化設計,建立扎實的程式設計基礎。

查看課程內容