Python 函式的參數傳遞方式:Passed by assignment
典型的參數傳遞方式有二種:
- Pass-by-value: 複製參數的值傳入,所以原參數內容不會被影響。
- Pass-by-reference: 傳入參數的參考,會影響原參數內容。
還有少數程式語言使用以下兩種傳遞方式:
- Pass-by-name: 將傳入的參數視為變數名稱或是字串,概念類似 string evaluation。
- Pass-by-value-result: 又稱 copy-in, copy-out,不直接傳入變數的參照,反而是將其複製一份傳入參照,最後再把結果指派回原先的變數。
如果以上四種就可以解釋完 Python 的參數傳遞方式,那或許也不需要寫這篇文章了(笑)。嚴格來說,Python 並不屬於以上四種傳遞方式,但是觀念上都是互通的,在這之前,我們必須先了解何謂 Immutable/Mutable。
Immutable Object and Mutable Object
Immutable 代表物件產生後就不可以被修改,反之 Mutable 則是可以被修改。舉例來說 Python 中
你可能會對 strings 比較好奇:「我常常像這種方式寫啊! string 怎麼會是 Immutable 呢?」
1
2
3
4
| s ="Hello"
s +=" World!"
print s
#Print Result: Hello World! |
Pass Immutable Object by Assignment
引用自官方文件中的 FAQ:
Remember that arguments are passed by assignment in Python. Since assignment just creates references to objects, there’s no alias between an argument name in the caller and callee, and so no call-by-reference per se. You can achieve the desired effect in a number of ways.
其實重點就在於一個字:Assignment。每個 Assignment 就會產生對於物件的一個參照。假設以下面的程式為例:
1
2
3
4
5
6
7
8
9
10
11
| def foo(a):
printid(a)# 取得 a 所參考物件的記憶體位址
a +=1
a =0
printid(a)
foo(a)
print a
#Print Result:
#140463882402880
#140463882402856
#0 |
Pass Mutable Object by Assignment
當傳入的參數指向的為 Mutable Object 時,狀況就稍微不同了:
1
2
3
4
5
6
7
8
9
10
11
12
| def foo(a):
printid(a)
a.append(1)
a =[] |
1
2
3
4
5
6
7
8
9
10
11
12
13
| def foo(a):
printid(a)
a.append(1)
a =[1,2]
a =[] |
總結
針對這個議題 Stackoverflow 說明得非常詳細,推薦大家一讀:
The parameter passed in is actually a reference to an object, but the reference is passed by value.
簡單來說,Python 的參數傳遞方式你必須注意:
- Immutable Object 參數傳遞行為同 pass-by-value。
- Mutable Object 參數傳遞行為同 pass-by-reference,但是不允許 re-assignment。