Python 腦筋急轉彎:為什麼「內容一樣」不代表「它們一樣」?搞懂 is 和 == 的差別
你可能在寫 Python 的時候遇過這個奇怪的現象:明明兩個變數印出來都是 [1, 2, 3],用 == 檢查是 True(正確),但換成 is 檢查卻變成了 False?
別擔心,這不是 Python 在耍大牌,也不是你的眼睛出錯。這背後其實牽扯到程式語言中一個非常重要的觀念:「內容(Value)」與「身分(Identity)」的區別。
想像你手上有兩支 iPhone 17
為了讓你秒懂,我們不用程式碼,先用生活中的例子來比喻:
想像你跟你朋友都買了一支黑色的 iPhone 17,規格一模一樣,連手機殼都選了同一款。
==(內容相等): 當我們問「這兩支手機是一樣的嗎?」如果是指型號、顏色、功能,答案是 Yes。它們在「價值」和「內容」上是平等的。is(身分相同): 當我們問「這兩支是『同一支』手機嗎?」答案顯然是 No。如果你不小心把你朋友的手機螢幕摔裂了,你的手機螢幕並不會跟著裂掉,因為它們是兩個獨立的實體,存在於空間中不同的位置。
在 Python 的世界裡,== 檢查的是手機型號,而 is 檢查的是手機序號(記憶體位址)。
1. ==:內容的檢查員 (Equality)
當你使用 == 時,你是在告訴 Python:「請幫我看看這兩個變數裡面裝的東西長得像不像?」
list_a = [1, 2, 3]
list_b = [1, 2, 3]
print(list_a == list_b) # 結果是 True
Python 會跑進這兩個列表裡,一個一個比對裡面的數字。既然都是 1, 2, 3,它就會開心地給你一個 True。
2. is:身分的檢查員 (Identity)
當你使用 is 時,情況就不同了。你是在問:「這兩個變數是不是指向記憶體中同一個『家』?」
print(list_a is list_b) # 結果是 False
雖然內容一模一樣,但 list_a 和 list_b 是在記憶體中分別佔用了兩個不同的空間。你可以想像成兩間裝潢一模一樣的房間,但門牌號碼(記憶體位址)是不一樣的。
在 Python 中,你可以用 id() 這個函式來查看這個「門牌號碼」:
* id(list_a) 可能會得到 140523456
* id(list_b) 可能會得到 140523789
因為門牌號碼不同,所以 is 就會說是 False。
那些讓人困惑的「例外」
有些時候,你可能會發現一些詭異的情況。例如:
a = 10
b = 10
print(a is b) # 竟然是 True?!
「等等,你剛剛不是說獨立創建就是不同實體嗎?」
這是因為 Python 為了節省效能,偷偷做了一個優化。對於像「小整數(-5 到 256)」或是「簡單字串」這類常用的資料,Python 會預先準備好一個「快取池」。當你建立 a = 10 和 b = 10 時,它們其實都共用了同一個預先建好的數字 10。
這就像是全台灣所有的「便利商店」雖然有很多家,但它們提供的「10元硬幣」在面額和意義上都是同一個公定標準,Python 覺得沒必要為了同樣的常用小數字一直開新空間。
那我該怎麼選?
知道這個秘密後,我們在寫程式時可以遵循這個簡單的守則:
- 大多數時候,請用
==: 如果你只是想比較兩個人的名字是不是都叫「小明」,用==就對了。 - 只有在特定的地方用
is:- 最常見的用法是跟
None比較:if x is None:。 - 因為
None在 Python 整個系統中永遠只有一個,用is速度最快也最準確。
- 最常見的用法是跟
結語
下次當你在 debug 時,如果發現判斷式不如預期,記得回頭想想:你是在比「內容」,還是在比「身分」?
== 就像在看兩個人是不是穿一樣的制服;而 is 則是在確認這兩個人是不是同一個靈魂。搞懂這點,你的 Python 之路就會走得更順暢囉!
0 留言
發表留言