函數的參數傳遞
函數參數傳遞有兩種方式,傳值和傳引用,傳值只是把變量的值復制一份給了實參,函數內部的操作不會改變函數外部變量的值,而傳引用傳遞的是外部變量的地址,函數內部直接操作函數外部變量的儲存空間,在調用函數之后,函數外部變量的值一般會改變
def Demo(a):a = a + 1print(id(a))if __name__ == '__main__':a = 3print(id(a)) # 140705335465056Demo(a) # 140705335465088print(id(a)) # 140705335465056
看到變量a在函數調用前后地址值沒有改變,證明在傳遞數值時傳遞的是變量的值,字符等類型也一樣,然后嘗試列表,元組
def Demo(a):a.append(3)print(id(a))if __name__ == '__main__':s = [1,2]print("value = " + str(s) + "address = " + str(id(s))) # value = [1, 2]address = 1574898786888Demo(s) # value = [1, 2, 3]address = 1574898786888print("value = " + str(s) + "address = " + str(id(s))) # value = [1, 2, 3]address = 1574898786888
函數調用前后地址值一致,證明傳遞的是引用,并且函數執行以后a的值也發生了改變,說明a.append()
是在s的內存中操作的
如果傳遞的是元組,應為元組不可修改,所以三次輸出的都是同一塊地址,但其實以元組為參數傳遞時傳遞的是值。
還有一種情況
def Demo(a):a[0].append(3)print("value = " + str(a) + "address = " + str(id(a)))if __name__ == '__main__':a = ([1,2], 2)print("value = " + str(a) + "address = " + str(id(a))) # value = ([1, 2], 2)address = 2616967970056Demo(a) # value = ([1, 2, 3], 2)address = 2616967970056print("value = " + str(a) + "address = " + str(id(a))) # value = ([1, 2, 3], 2)address = 2616967970056
如果元組中的元素是列表,在調用函數前后,函數外部的a也發生了變化,根據剛開始說的,這感覺是在傳引用,但其實不是,對于函數外部的a來說,他的第0個元素始終是<class 'list'>
,至于列表中元素有沒有發生變化,元組并不關心,元組判斷元素有沒有改變判斷的是元素的地址有沒有改變,而調用append()函數時,傳遞的是可變元素列表,地址值不會發生改變,這也就是為什么元組不可變,但如果元組中的數據是可變類型的話該數據就可變的原因
總結
python有兩種數據類型,可變和不可變數據,對于可變數據類型,諸如列表,字典,集合在函數傳參時傳引用,對于不可變數據類型,如數值,字符,元組,在函數傳參時傳值,但更準確的來說,python函數傳參時使用傳對象引用的方式,如果函數收到的是一個可變對象(比如字典或者列表)的引用,就能修改對象的原始值--相當于通過“傳引用”來傳遞對象。如果函數收到的是一個不可變對象(比如數字、字符或者元組)的引用,就不能直接修改原始對象--相當于通過“傳值’來傳遞對象。
最后還是要注意像元組中數據是可變類型的情況
參考鏈接1
參考鏈接2