學會了用 def 「自動果汁機」(自訂函式),也徹底搞懂了 return 與 print 的麥當勞點餐哲學。
但在大量使用函式的同時,新手幾乎 100% 會撞上一個神秘的邏輯牆。
你可能會寫出類似這樣的程式碼:
money = 100 # 我原本有 100 元
def spend_money():
money = 20 # 在函式裡花到剩下 20 元
print("函式內部的 money:", money)
spend_money()
print("函式外面的 money:", money)
在你執行之前,直覺想一下:外面的 money 應該變成 20 了對吧?
但當你按下執行(▶),終端機竟然會印出:
函式內部的 money: 20
函式外面的 money: 100
外面的錢居然完全沒有變!
今天要聊聊程式世界裡的兩個平行宇宙
🏠 輕鬆譬喻:客廳共用 vs 自己房間開趴
為什麼會這樣?
因為 Python 為了保護程式不互相干擾,對變數的「生存範圍(Scope)」劃分得非常嚴格。
我們可以用一棟房子來理解:
1. 全域變數(Global)=「客廳的公共物品」
• 寫在所有函式外面的變數,就像放在家裡大客廳中央的電視。
• 家裡的每個人(所有的函式)都可以走出來看這台電視、讀取它的資料。
2. 區域變數(Local)=「自己房間裡的私人物品」
• 寫在函式內部的變數,就像是你鎖在自己房間裡的私人物品。
• 重點來了:你在自己房間裡重新寫了一張叫 money 的便利貼(宣告同名變數),這個 money 就只屬於你的房間。
你在房間裡把這個 money 改成 20,大客廳裡那個原本的 money 便利貼根本聽不到,也完全不會受到影響!
💡 新手村備忘錄:函式執行完畢後,它所創造的房間就會被「瞬間炸毀」。留在裡面的區域變數也會跟著消失!
🕵️ 案發現場:電腦是怎麼看這段 Code 的?
我們回頭用 Day 3 學的「便利貼哲學」,逆向通靈一下剛剛的靈異代碼:
這就是為什麼「外面的錢完全沒有變」的原因。
🛠️ 破局之法:如果我真的想在房間裡改變客廳的變數呢?
雖然 Python 預設不允許房間干擾客廳,但如果你今天真的要在函式內部修改全域變數,有兩種常見的做法:
做法 A:最優雅的做法——用 return 把結果傳出來(強烈推薦!)
不要在房間裡瞎搞,把算好的結果當成成品交出來,讓客廳的人去接住它:
money = 100
def spend_money(current_money):
new_money = current_money - 80 # 扣掉 80 元
return new_money # 把算好的成品送出去
#客廳的人撕掉舊標籤,貼到送出來的新成品上
money = spend_money(money) // 把return出來的值接住
print("花完錢後客廳的 money:", money) # 成功變成 20!
做法 B:使用強行打破宇宙壁壘的關鍵字 global(少用為妙)
在函式內部大喊一聲 global,告訴電腦:「老子現在要直接動客廳的東西!」
money = 100
def spend_money():
global money # 打破平行宇宙!直接指名客廳的 money
money = 20 # 這會直接修改全域的變數
spend_money()
print("強行修改後外面的 money:", money) # 變成 20 啦!
⚠️ 警告:雖然 global 看起來很方便,但在大型專案裡如果到處亂用,會讓程式變得很難 debug。因為你根本不知道是哪一個房間偷偷改了客廳的東西,導致整家公司亂成一團。因此,推薦多使用做法 A!
今日結語:你釐清宇宙的邊界了嗎?
今天我們成功釐清了全域與區域變數的平行宇宙觀念。搞懂這個,你以後在寫複雜程式呼叫函式時,就不會再為了變數莫名其妙沒改變而抓狂了!
接下來聊更刺激的話題。
當玩家亂輸入資料、或是網路斷線時,程式往往會瞬間「閃退」死給你看。我們要學會用 try-except 幫程式裝上安全氣囊,讓它就算撞車也能優雅地活下來!
🧑💻 今日小作業
請看看以下程式碼,不實際執行,在腦海中通靈一下:最後一行會印出什麼數字?
x = 10
def my_magic():
x = 50
return x
my_magic()
print(x) # 請問這裡會印出 10 還是 50?