Python中的變量是沒有類型的,我們可以把它看做一個(*void)類型的指針,變量是可以指向任何對象的,而對象才是有類型的。
Python中的對象有可變對象(number,string,tuple等)和不可變對象之分(list,dict等)。
值傳遞(passl-by-value)過程中,被調函數的形式參數作為被調函數的局部變量處理,即在堆棧中開辟了內存空間以存放由主調函數放進來的實參的值,從而成為了實參的一個副本。值傳遞的特點是被調函數對形式參數的任何操作都是作為局部變量進行,不會影響主調函數的實參變量的值。(被調函數新開辟內存空間存放的是實參的副本值)
引用傳遞(pass-by-reference)過程中,被調函數的形式參數雖然也作為局部變量在堆棧中開辟了內存空間,但是這時存放的是由主調函數放進來的實參變量的地址。被調函數對形參的任何操作都被處理成間接尋址,即通過堆棧中存放的地址訪問主調函數中的實參變量。正因為如此,被調函數對形參做的任何操作都影響了主調函數中的實參變量。(被調函數新開辟內存空間存放的是實參的地址)
1. 不可變對象作為函數參數,相當於C語言的值傳遞。
1 def test(c): 2 print("test before ") 3 print(id(c)) #一開始傳遞進來的是對不可變數據類型a(數字類型)的引用 4 c += 2 #數字改變后有一個新的指針指向3所在內存空間,但原來指向2的指針a(內存地址空間依舊存在)未改變 5 print("test after ") 6 print(id(c)) #故c的內存地址改變 7 return c 8 9 10 if __name__ == "__main__": 11 a = 2 12 print(id(a)) 13 n = test(a) #4 14 print(a) #2 15 print(id(a))
1 最終 2 輸出的值為 3 1547916096 4 test before 5 1547916096 6 test after 7 1547916160 8 2 9 1547916096
2. 可變對象作為函數參數,相當於C語言的引用傳遞。(因列表是可變數據類型,作為參數傳遞實則是傳遞對列表的引用,修改更新列表值后依舊引用不變)
1 def test(list2): 2 print("test before ") 3 print(id(list2)) #221 4 list2[1] = 30 5 print("test after ") 6 print(id(list2)) #221 7 return list2 8 9 if __name__ == "__main__": 10 list1 = ["loleina", 25, 'female'] 11 print(id(list1)) #221 12 list3 = test(list1) 13 print(list1) #["loleina",30, 'female'] 14 print(id(list1)) #221 15 print(id(list3))
1 17192136 2 test before 3 17192136 4 test after 5 17192136 6 ['loleina', 30, 'female'] 7 17192136 8 17192136