Python学习之参数(一)
Python學習之參數(一)
文章目錄
- Python學習之參數(一)
- 參數的傳遞
- 避免可變參數的修改
- 參考資料
參數的傳遞
所有的參數實際上都是通過指針進行傳遞的。作為參數被傳遞的對象從來不自動拷貝。
在函數內部的參數名的賦值不會影響調用者。
如果傳入的是可變對象,那么在函數內就可以就地改變這個可變對象,這可能會影響調用者。
Python通過賦值進行傳遞的機制與C++的引用參數選項并不完全相同,實際上它與C語言的參數傳遞模型相當相似。
不可變參數“通過值”進行傳遞。像整數和字符串這樣的對象是通過對象引用而不是拷貝進行傳遞的,但是因為你無論怎樣都不可能在原處改變不可變對象,所以實際效果就像創建了一份拷貝。
可變對象是通過指針進行傳遞的。例如,像列表和字典這樣的對象也是通過對象引用進行傳遞的,這一點與C語言使用指針傳遞數組很相似:可變對象能夠在函數內部進行原處改變,這一點和C數組很像。
以上只是偏重于理論的敘述,如果想搞清楚Python的參數傳遞機制,恐怕要研究幾個例子。
考慮如下代碼:
>>> def f(a): # a is assigned to (references) the passed objecta = 99 # Changes local variable a only >>> b = 88 >>> f(b) # a and b both reference same 88 initially >>> print(b) # b is not changed 88第3行,b引用了88,可以認為b指向了88;
第4行,調用函數f,把b傳了進去,實際上傳遞的是一個指針;
第1行,這里的a擁有了b的值,實際上是a也指向88;
第2行,a又指向了99;
第5行,打印b,此時b已然指向88,所以結果是88。
咱們再看一個例子。
>>> def changer(a, b): # Arguments assigned references to objectsa = 2 # Changes local name's value onlyb[0] = 'spam' # Changes shared object in place >>> X = 1 >>> L = [1, 2] # Caller: >>> changer(X, L) # Pass immutable and mutable objects >>> X, L # X is unchanged, L is different! (1, ['spam', 2])從第8行的結果來看,X 并沒有改變,但是 L 從 [1, 2] 改變為 [‘spam’, 2]
X 沒有改變,這和第一個例子是同樣的道理。
我們分析一下 L 為什么會改變。第1行的b也是一個本地變量,但是一個可變對象傳給了它——b指向了一個列表,它和L共享同一個對象。第3行,對b[0]進行賦值的結果會在函數返回后影響L的值。
下圖中說明了函數調用前和調用中變量名與對象的綁定關系。
在調用changer函數之前,X 指向 1,L 指向列表 [1, 2] ;在函數調用的時候,X的值(對象1的地址)被傳遞給 a,所以 a 也指向1,同理,b 指向列表 [1, 2] ;因為 1 是不可變對象,所以 a = 2 并不會修改對象 1,而是使 a 指向 2,但是列表是可變對象, b[0] = ‘spam’ 確實修改了列表 [1, 2] ,使其變成了 [‘spam’, 2]。
如果上面的內容依然令你困惑的話,你可以這么理解,通過函數調用進行參數賦值與運行下面一系列簡單的賦值語句是等效的:
>>> X = 1 >>> a = X # They share the same object >>> a = 2 # Resets 'a' only, 'X' is still 1 >>> print(X) 1 >>> L = [1, 2] >>> b = L # They share the same object >>> b[0] = 'spam' # In-place change: 'L' sees the change too >>> print(L) ['spam', 2]避免可變參數的修改
對可變參數的原處修改的行為不是一個 bug——它只是參數傳遞在Python中的工作方式。在Python中,默認通過引用(也就是指針)進行參數傳遞,因為這通常是我們想要的。這意味著不需要創建多個拷貝就可以傳遞很大的對象,并且能夠按照需要方便地更新這些對象。
如果不想要函數內部在原處的修改影響到傳遞給他的對象,那么可以創建一個原對象的拷貝。例如:
L = [1, 2] changer(X, L[:]) #通過切片傳遞拷貝,所以L不會改變如果不想改變傳入的對象,無論函數是如何調用的,我們同樣可以在函數內部進行拷貝。
def changer(a, b):b = b[:] # Copy input list so we don't impact callera = 2b[0] = 'spam' # Changes our list copy only—未完待續—
參考資料
《Python學習手冊(第4版)》,機械工業出版社
《Learning Python 5th Edition》, O’Reilly
總結
以上是生活随笔為你收集整理的Python学习之参数(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python学习之zip函数
- 下一篇: Python学习之函数返回多个值