爲回答網友問題,而造此博文

# def spam(eggs):
#     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........

初學...表達能力有限,希望有所幫助.















發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章