iT邦幫忙

1

【Python】9.世界觀的碰撞:全域變數與區域變數的「平行宇宙」陷阱

  • 分享至 

  • xImage
  •  

學會了用 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

外面的錢居然完全沒有變!

今天要聊聊程式世界裡的兩個平行宇宙

「全域變數(Global Variable)」與「區域變數(Local Variable)」

🏠 輕鬆譬喻:客廳共用 vs 自己房間開趴

為什麼會這樣?

因為 Python 為了保護程式不互相干擾,對變數的「生存範圍(Scope)」劃分得非常嚴格。

我們可以用一棟房子來理解:

1. 全域變數(Global)=「客廳的公共物品」

• 寫在所有函式外面的變數,就像放在家裡大客廳中央的電視。
• 家裡的每個人(所有的函式)都可以走出來看這台電視、讀取它的資料。

2. 區域變數(Local)=「自己房間裡的私人物品」

• 寫在函式內部的變數,就像是你鎖在自己房間裡的私人物品。
• 重點來了:你在自己房間裡重新寫了一張叫 money 的便利貼(宣告同名變數),這個 money 就只屬於你的房間。

你在房間裡把這個 money 改成 20,大客廳裡那個原本的 money 便利貼根本聽不到,也完全不會受到影響!

💡 新手村備忘錄:函式執行完畢後,它所創造的房間就會被「瞬間炸毀」。留在裡面的區域變數也會跟著消失!

🕵️ 案發現場:電腦是怎麼看這段 Code 的?

我們回頭用 Day 3 學的「便利貼哲學」,逆向通靈一下剛剛的靈異代碼:

  1. money = 100:電腦在全域宇宙(客廳)創造了 100,貼上 money 標籤。
  2. def spend_money()::電腦在大腦裡登記了一台叫 spend_money 的機器,此時不執行。
  3. spend_money():主程式呼叫機器,電腦立刻開闢了一個區域宇宙(專屬房間)。
  4. money = 20(在房間內):電腦在房間宇宙裡創造了 20,並貼上一張「僅限房內使用」的 money 標籤。這跟客廳的標籤同名,但是是不同的平行宇宙!
  5. print(在房間內):印出房內的 money(20)。
  6. 函式結束:房間宇宙崩塌!房內的 money 標籤與 20 灰飛煙滅。
  7. print(在客廳):回到全域宇宙,電腦看著客廳中央,那張原本的 money 標籤依然好端端地貼在 100 上面。

這就是為什麼「外面的錢完全沒有變」的原因。

🛠️ 破局之法:如果我真的想在房間裡改變客廳的變數呢?

雖然 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?

圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
JACK_CAT
iT邦新手 4 級 ‧ 2026-07-16 17:04:33

答案是 10 嗎??? 因為沒有接住裡面的return??

reneezhu iT邦新手 5 級 ‧ 2026-07-16 19:41:33 檢舉

對的,是10

JACK_CAT iT邦新手 4 級 ‧ 2026-07-17 09:14:05 檢舉

謝謝您!

我要留言

立即登入留言