1. 傳值與傳址的區別
傳值就是傳入一個參數的值,傳址就是傳入一個參數的地址,也就是內存的地址(相當于指針)。他們的區別是如果函數里面對傳入的參數重新賦值,函數外的全局變量是否相應改變:用傳值傳入的參數是不會改變的,用傳址傳入就會。
def a(n): n[2] = 100 print(n) return Nonedef b(n): n += 100 print(n) return Nonean = [1,2,3,4,5]bn = 10print(an)a(an)print(an)print(bn)b(bn)print(bn)[1, 2, 3, 4, 5][1, 2, 100, 4, 5][1, 2, 100, 4, 5]1011010
在上面的例子中,an是一個list,將其作為實參傳入函數a中,a對其第三個元素進行修改。a執行結束后再次打印an,發現里面的元素的確發生變化,這就是傳址操作。bn代表一個數字,將其傳入函數b,并做修改,b執行結束后再次打印bn,沒有變化,這是傳值操作。
2. Python中傳值與傳址的規律
Python是不允許程序員選擇采用傳值還是傳址的。Python參數傳遞采用的是“傳對象引用”的方式,實際上,這種方式相當于傳值和傳址的一種綜合。
如果函數收到的是一個可變對象(比如字典或者列表)的引用,就能修改對象的原始值——相當于傳址。如果函數收到的是一個不可變對象(比如數字、字符或者元組)的引用,就不能直接修改原始對象——相當于傳值。所以python的傳值和傳址是根據傳入參數的類型來選擇的。
傳值的參數類型:數字,字符串,元組
傳址的參數類型:列表,字典
3. 內置函數id
內置函數id,負責顯示一個變量或者數據在內存中的地址,有時可以用來檢測所使用的對象是否為同一個,幫助區別傳值與傳址操作。
但是id在有些情況下比較特殊,注意下面的例子。
a = 100b = 200 print(id(a))print(id(b))c = aprint(id(c))print(a is c)a += 300print(a)print(c)print(a is c)print(id(a))print(id(c))154949555215494987521549495552True400100False936381281549495552
為了提高內存利用效率,對于一些簡單的對象,如一些數值較小的int對象,python采取重用對象內存的辦法。如指向a=100,c=100時,由于100作為簡單的int類型且數值小,python不會兩次為其分配內存,而是只分配一次,然后將a與c同時指向已分配的對象。但是當a的值發生變化時,會單獨為a重新分配一個新的內存。
4. list傳值與傳址
list類型使用簡單的賦值操作,是傳址。
a = [1,2,3,4,5]b = aprint(a)b[2] = 333print(a)print(b)print(id(a))print(id(b))[1, 2, 3, 4, 5][1, 2, 333, 4, 5][1, 2, 333, 4, 5]9614247296142472
copy函數是淺拷貝,是傳值。python2中,需要import copy模塊,python3可直接使用。
a = [1,2,3,4,5]b = a.copy()print(a)b[2] = 333print(a)print(b)print(id(a))print(id(b))[1, 2, 3, 4, 5][1, 2, 3, 4, 5][1, 2, 333, 4, 5]9299053696202632
新聞熱點
疑難解答