# eggs.append(1)
# eggs = [2, 3]
#
# ham = [0]
# spam(ham)
# print(ham)
#1.首先對你看的博文中的代碼進行等價改動 --- 個人代碼習慣問題
ham = [0]
def span(eggs):
eggs.append(1)
eggs = [2, 3]
spam(ham)
print(ham)
先科普下原理性的只是 --- 來自官方API
1.python中函數定義是一個可執行語句(邏輯語句,而不是物理語句),函數的執行綁定當前本地命名空間中的函數名和一個函數對象(圍繞該函數可執行代碼的包裝器).函數對象中包含一個對當前全局命名空間的一個引用,當該函數被調用,該引用被當做全局命名空間使用(意思是可以引用全局命名空間中的內容)
函數的執行(即被調用/加載到內存),會爲該函數創建一個新的本地符號表,更確切來說,函數中所有變量的賦值都會把值存儲在本地符號表中,當變量被應用是查找順序:
當前(被調)函數本地符號表 --> 主調函數本地符號表 --> 全局符號表
--> python內置符號表(python解釋器啓動時也是需要加載一些常量啊什麼的[e.g:quit(), exit()等]).
因此,全局變量不能在函數內部被賦值(除非使用golable關鍵字進行相關操作....).....這句廢話不翻譯了....
第二段: 走起
函數被調用時,實參會被引入到被調函數的本地符號表中,因此參數傳遞時"值傳遞"(這三個字不準確,看箭頭)(該值指的是對象的引用的值,不是對象的值),當一個函數被調用會爲該函數創建一個新的本地符號表
紅箭頭解釋部分:
更準確的描述是參數傳遞的是對象引用,後一句.....不理解啥意思.......
本人,也是初學....只是對API多瞄了幾眼,希望能從本質上理解python,所以這樣答問.....不知喜否?
科普完畢,下面來具體分析你的代碼
ham = [0]
def span(eggs):
eggs.append(1)
eggs = [2, 3]
span(ham)
print(ham)
spam(ham)
調用該函數,把ham賦值給eggs --- 這也是上文說的函數內部的賦值行爲,因而會把實參ham引入到函數span的本地符號表,在執行eggs.append(1)時,首先在本地符號表中找到ham,然後在聲明ham時ham被引入的符號表中找到ham,找到後當然是向ham列表實體中追加元素1了...over
eggs = [2,3]
這句執行後,eggs即當前函數本地符號表中的ham不再指向聲明ham時ham被引入的符號表中的ham,而指向列表[2, 3]實體,即這句執行並沒有改變ham所在符號表中的ham,只是創建了一個新的列表,並且改變了當前函數span符號表中ham即eggs的指向
print(ham)
執行這句時,即調用print函數,ham也會被引入到print函數的本地符號表,在print函數內部把ham寫入到流中時,會在print函數內部本地符號表中找到ham,然後在聲明ham時ham被引入的符號表中找到ham,並把ham寫入流中,輸出到屏幕
此時找到的ham中內容被span函數追加了一個元素,其元素爲[0,1]
............over....................over....................over....................over....................over....................over........
初學...表達能力有限,希望有所幫助.