Python 函數參數引用(傳值/傳址)/copy/deepcopy

精簡版:

傳值:被調函數局部變量改變不會影響主調函數局部變量

傳址:被調函數局部變量改變會影響主調函數局部變量

Python參數傳遞方式:傳遞對象引用(傳值和傳址的混合方式),如果是數字,字符串,元組則傳值;如果是列表,字典則傳址;

copy使用場景:列表或字典,且內部元素爲數字,字符串或元組

deepcopy使用場景:列表或字典,且內部元素包含列表或字典

完整版:

1.傳值和傳址的區別

傳值就是傳入一個參數的值,傳址就是傳入一個參數的地址,也就是內存的地址(相當於指針)。他們的區別是如果函數裏面對傳入的參數重新賦值,函數外的全局變量是否相應改變,用傳值傳入的參數是不會改變的,用傳址傳入就會改變。

1 a=1
2 def f(b):
3     b=2
4 f(a)
5 print a

例如這段代碼裏面,首先聲明a的值爲1,把a作爲參數傳入到函數f裏面,函數f裏面對b重新賦值爲2,如果是傳值的形式傳入a的話,a的值是不會變的,依然爲1,如果以傳址的形式(但是這個不是程序員能決定的)傳入a,a就會變成2。這個就是傳值和傳址的區別。

 

2. Python中的傳址和傳值是怎樣的呢?

Python是不允許程序員選擇採用傳值還是傳址的。Python參數傳遞採用的肯定是“傳對象引用”的方式。實際上,這種方式相當於傳值和傳址的一種綜合。

如果函數收到的是一個可變對象(比如字典或者列表)的引用,就能修改對象的原始值——相當於傳址。如果函數收到的是一個不可變對象(比如數字、字符或者元組)的引用(其實也是對象地址!!!),就不能直接修改原始對象——相當於傳值。

所以python的傳值和傳址是根據傳入參數的類型來選擇的

傳值的參數類型:數字,字符串,元組(immutable)

傳址的參數類型:列表,字典(mutable)

1 a=1
2 def f(a):
3     a+=1
4 f(a)
5 print a

這段代碼裏面,因爲a是數字類型,所以是傳值的方式,a的值並不會變,輸出爲1

1 a=[1]
2 def f(a):
3     a[0]+=1
4 f(a)
5 print a

這段代碼裏面,因爲a的類型是列表,所以是傳址的形式,a[0]的值會改變,輸出爲[2]

3. copy和deepcopy

 不止是函數裏面,函數外面的引用也同樣遵循這個規則:

複製代碼
1 a=1
2 b=a
3 a=2
4 print a,b
5 a=[1]
6 b=a
7 a[0]=2
8 print a,b
複製代碼

第一個輸出爲2,1,第二個輸出爲 [2] [2]

b=a

所以在python中,當運行上面的代碼時,如果a是字典或者列表的話,程序執行的操作並不是新建一個b變量,然後a的值複製給b,而是新建一個b變量,把b的值指向a,也就是相當於在c語言裏面的新建一個指向a的指針。
所以當a的值發生改變時,b的值會相應改變。

但是,當我們想新建一個與a的值相等的b變量,同時b的值與a的值沒有關聯時,要怎麼做?這時就用到copy與deepcopy了

複製代碼
 1 import copy
 2 
 3 a=[1,2,3]
 4 b=a
 5 a.append(4)
 6 print a,b
 7 
 8 a=[1,2,3]
 9 b=copy.copy(a)
10 a.append(4)
11 print a,b
複製代碼

上面的輸出爲:

1 [1, 2, 3, 4] [1, 2, 3, 4]
2 [1, 2, 3, 4] [1, 2, 3]

這裏用了copy來讓b與a相等,後面如果修改了a的值,b的值並不會改變。看來copy已經可以實現我們上面的提到的需求了,那麼deepcopy又有什麼用?

如果我們遇到這種情況,copy就解決不了了

1 a=[1,[1,2],3]
2 b=copy.copy(a)
3 a[1].append(4)
4 print a,b

這裏輸出的結果爲:[1, [1, 2, 4], 3] [1, [1, 2, 4], 3]  ,這樣的結果明顯不是我們想要的

當列表或字典參數裏面的值是列表或字典時,copy並不會複製參數裏面的列表或字典,這時就要用到deepcopy了

1 a=[1,[1,2],3]
2 b=copy.deepcopy(a)
3 a[1].append(4)
4 print a,b

輸出的結果爲:[1, [1, 2, 4], 3] [1, [1, 2], 3]

 

參考資料:http://www.cnblogs.com/Xjng/p/3829368.html

本文轉自:http://www.cnblogs.com/CheeseZH/p/5165283.html

作者: ZH奶酪——張賀 
Q Q: 1203456195 
郵箱: [email protected] 
出處: http://www.cnblogs.com/CheeseZH/ 
* 本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。

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