一個看似簡單的謎題揭示了 Python 最基本的概念之一


挑戰

在深入解釋之前,我們先來做個小測試。看一下這段 Python 程式碼,預測一下它會輸出什麼:

a = 500
b = a
a = a + 100

list1 = [1, 2]
list2 = list1
list1.append(3)

print(f"b is {b}")
print(f"list2 is {list2}")

您認為輸出結果會是什麼?

A) b is 600list2 is [1, 2]

B) b is 500list2 is [1, 2, 3]

C) b is 500list2 is [1, 2]

D) b is 600list2 is [1, 2, 3]

花點時間仔細想想。程式碼看起來很簡單,但其中有一些微妙之處,即使是經驗豐富的開發人員也會犯錯。

當您準備好答案時,請向下滾動...


答案

正確答案是Bb is 500list2 is [1, 2, 3]

如果你答對了,太棒了!如果沒有,也不用擔心──這種行為讓許多 Python 開發者感到困惑。理解這一點的關鍵在於一個許多教程都忽略的關鍵概念。

揭開謎底

我們程式碼中的不同行為並非隨機或不一致。它們是 Python 處理兩種不同類型物件(可變物件不可變物件)的邏輯結果。

讓我們一步一步分析到底發生了什麼事。

第一部分:整數驚喜

a = 500
b = a
a = a + 100

Python 實際做的事情如下:

  1. a = 500 :建立一個包含500整數物件,並指派名稱a來指向它

  2. b = a :使b指向a指向的同一個500物件

  3. a = a + 100 :這是關鍵的一行。它計算a + 100 (即600 ),建立一個包含600全新整數物件,並將a重新賦值給這個新物件。

關鍵在於:整數在 Python 中是不可變的。整數物件一旦建立,就無法變更其值。當你寫a = a + 100時,Python 不會修改現有的500物件,而是創造一個新的600物件。

由於b從未被重新賦值,它仍然指向原始的500物件。因此: b is 500

第二部:名單情節轉折

list1 = [1, 2]
list2 = list1
list1.append(3)

現在讓我們追蹤清單操作:

  1. list1 = [1, 2] :建立一個包含[1, 2]的列表物件,並指派list1指向它

  2. list2 = list1 :使list2指向list1指向的相同列表物件

  3. list1.append(3) :差別在於-它透過向現有清單物件加入3來修改它

關鍵見解:清單在 Python 中是可變的。呼叫append()時,實際上是在修改現有列表物件,而不是建立新物件。

由於list1list2都指向同一個列表物件,並且該對像已被修改,因此兩個名稱現在都指向[1, 2, 3] 。因此: list2 is [1, 2, 3]

更大的圖景:變數是名稱,而不是盒子

這個謎題說明了許多開發人員誤解的有關 Python 的一個基本事實:變數是指向物件的名稱,而不是保存值的容器

可以這樣想:

  • 變數名就像一張寫有名字的便條

  • 物件就像包含實際資料的盒子

  • 任務將姓名標籤貼在盒子上

  • 多個名稱可以指向同一個框

當你理解了這個思考模型,這個神祕程式碼就完全說得通了:

  • 對於不可變物件(整數),操作會建立新的框並移動名稱標籤以指向它們

  • 對於可變物件(清單),操作會修改現有方塊的內容,但指向該方塊的所有名稱標籤保持不變

為什麼這很重要

理解可變性不僅僅是學術層面的——它能防止真正的 bug。想想這個常見的 Python 陷阱:

def add_item(item, target_list=[]):
    target_list.append(item)
    return target_list

# This doesn't work as expected!
list1 = add_item("first")
list2 = add_item("second")  # Oops! list2 is now ["first", "second"]

預設列表[]是可變的,因此所有函數呼叫共享同一個列表物件。一旦你理解了物體的可變性,這種行為就變得可預測,而不是神秘莫測。

測試你的理解

現在您已經知道了秘密,請嘗試預測此程式碼的輸出:

x = "hello"
y = x
x = x + " world"

dict1 = {"key": "value"}
dict2 = dict1
dict1["key"] = "modified"

print(f"y is '{y}'")
print(f"dict2 is {dict2}")

答案: y is 'hello'dict2 is {'key': 'modified'} (字串是不可變的,字典是可變的)。

總結

一旦你了解底層模型,你就會發現 Python 的變數系統非常優雅。變數本身並不包含物件,而是指向物件。指向的物件是否可修改取決於它的可變性。

這個概念解釋了無數乍看之下似乎很神秘的 Python 行為。掌握它,你會發現 Python 程式碼更可預測且易於除錯。

理解可變性只是 Python 眾多優雅概念中的一個,這些概念讓 Python 變得強大。一旦你理解了這個規律,你就會開始在程式碼的任何地方都能辨識它。


還有哪些 Python 謎題困擾著你?在留言區分享你的例子-或許有比你想像的更簡單的解釋!如果你覺得這篇文章有幫助,請關注,了解更多 Python 洞見,揭開程式碼背後的神秘面紗。


Aaron Rose 是tech-reader.blog的軟體工程師和技術作家,也是《像天才一樣思考》一書的作者。


原文出處:https://dev.to/aaron_rose_0787cc8b4775a0/python-mystery-quiz-can-you-crack-this-code-3o53


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝10   💬6   ❤️11
448
🥈
我愛JS
📝1   💬6   ❤️4
93
🥉
AppleLily
📝1   💬4   ❤️1
46
#4
💬2  
6
#5
💬1  
5
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次