首先還是應該科普下函式引數傳遞機制,傳值和傳引用是什麼意思?
函式引數傳遞機制問題在本質上是呼叫函式(過程)和被呼叫函式(過程)在呼叫發生時進行通訊的方法問題。基本的引數傳遞機制有兩種:值傳遞和引用傳遞。
值傳遞(passl-by-value)過程中,被調函式的形式引數作為被調函式的區域性變數處理,即在堆疊中開闢了記憶體空間以存放由主調函式放進來的實參的值,從而成為了實參的乙個副本。值傳遞的特點是被調函式對形式引數的任何操作都是作為區域性變數進行,不會影響主調函式的實參變數的值。
引用傳遞(pass-by-reference)過程中,被調函式的形式引數雖然也作為區域性變數在堆疊中開闢了記憶體空間,但是這時存放的是由主調函式放進來的實參變數的位址。被調函式對形參的任何操作都被處理成間接定址,即通過堆疊中存放的位址訪問主調函式中的實參變數。正因為如此,被調函式對形參做的任何操作都影響了主調函式中的實參變數。
在python中實際又是怎麼樣的呢?
先看乙個簡單的例子:
from ctypes import *執行後結果如下:importos.path
importsys deftest(c): print "test before " printid(c) c+=2 print "test after +" printid(c) returnc defprintit(t): for i inrange(len(t)): printt[i] if __name__=="__main__": a=2 print "main before invoke test" printid(a) n=test(a) print "main afterf invoke test" printa printid(a)
>>>main before invoke testid函式可以獲得物件的記憶體位址.很明顯從上面例子可以看出,將a變數作為引數傳遞給了test函式,傳遞了a的乙個引用,把a的位址傳遞過去了,所以在函式內獲取的變數c的位址跟變數a的位址是一樣的,但是在函式內,對c進行賦值運算,c的值從2變成了4,實際上2和4所佔的記憶體空間都還是存在的,賦值運算後,c指向4所在的記憶體。而a仍然指向2所在的記憶體,所以後面列印a,其值還是2.39601564test before
39601564test after +
39601540main afterf invoke test
239601564
如果還不能理解,先看下面例子
>>> a=1
>>> b=1
>>> id(a)
40650152
>>> id(b)
40650152
>>> a=2
>>> id(a)
40650140
a和b都是int型別的值,值都是1,而且記憶體位址都是一樣的,這已經表明了在python中,可以有多個引用指向同乙個記憶體(畫了乙個很挫的圖,見諒),在給a賦值為2後,再次檢視a的記憶體位址,都已經變化了
而基於最前面的例子,大概可以這樣描述:
那python函式傳參就是傳引用?然後傳參的值在被調函式內被修改也不影響主調函式的實參變數的值?再來看個例子。
from ctypes import *實際值為:importos.path
importsys deftest(list2): print "test before " printid(list2) list2[1]=30 print "test after +" printid(list2) returnlist2 defprintit(t): for i inrange(len(t)): printt[i] if __name__=="__main__": list1=["loleina",25,'female'] print "main before invoke test" printid(list1) list3=test(list1) print "main afterf invoke test" printlist1 printid(list1)
>>>main before invoke test發現一樣的傳值,而第二個變數居然變化,為啥呢?64129944test before
64129944test after +
64129944main afterf invoke test
['loleina', 30, 'female'] 64129944
>>> list1=[1,2]結論:python不允許程式設計師選擇採用傳值還是傳引用。python引數傳遞採用的肯定是「傳物件引用」的方式。這種方式相當於傳值和傳引用的一種綜合。如果函式收到的是乙個可變物件(比如字典或者列表)的引用,就能修改物件的原始值--相當於通過「傳引用」來傳遞物件。如果函式收到的是乙個不可變物件(比如數字、字元或者元組)的引用,就不能直接修改原始物件--相當於通過「傳值'來傳遞物件。>>>id(list1)
64185208
>>> list1[0]=[0]
>>>list1
[[0], 2]
>>>id(list1) 64185208
python函式傳參是傳值還是傳引用?
首先還是應該科普下函式引數傳遞機制 傳值和傳引用是什麼意思?函式引數傳遞機制問題在本質上是呼叫函式 過程 和被呼叫函式 過程 在呼叫發生時進行通訊的方法問題。基本的引數傳遞機制有兩種 值傳遞和引用傳遞。值傳遞 passl by value 過程中,被調函式的形式引數作為被調函式的區域性變數處理,即在...
python函式傳參是傳值還是傳引用?
首先還是應該科普下函式引數傳遞機制,傳值和傳引用是什麼意思?函式引數傳遞機制問題在本質上是呼叫函式 過程 和被呼叫函式 過程 在呼叫發生時進行通訊的方法問題。基本的引數傳遞機制有兩種 值傳遞和引用傳遞。值傳遞 passl by value 過程中,被調函式的形式引數作為被調函式的區域性變數處理,即在...
python函式傳參是傳值還是傳引用?
函式引數傳遞機制問題在本質上是呼叫函式 過程 和被呼叫函式 過程 在呼叫發生時進行通訊的方法問題。基本的引數傳遞機制有兩種 值傳遞和引用傳遞。值傳遞 passl by value 過程中,被調函式的形式引數作為被調函式的區域性變數處理,即在堆疊中開闢了記憶體空間以存放由主調函式放進來的實參的值,從而...