Python基礎(chǔ)之值傳遞和引用傳遞詳解
在python中,向函數(shù)傳遞參數(shù)的類(lèi)型有兩種,一種是值傳遞,還有一種是引用傳遞,如果你恰恰好會(huì)一點(diǎn)c基礎(chǔ),你可以理解為前者為傳遞形參,而后者傳遞指針。本篇文章將探究python的值傳遞和引用傳遞。
文本所依賴的python環(huán)境為:

什么是值傳遞和引用傳遞
值傳遞,我們可以理解為傳遞了一個(gè)副本過(guò)去,即變量的拷貝,修改副本值不會(huì)影響原先的值,例如:
def modify_x(x):
x = 99
print("函數(shù)中修改過(guò)后的值: " , x)
x=66
modify_x(x)
print("執(zhí)行modify_x函數(shù)后的值:" , x)在上述代碼中,我們定義了一個(gè)變量x,并賦值為66,而后將x傳入其modify_x函數(shù)中,在函數(shù)中,我們將x賦值為99,打印一下函數(shù)中的x值,函數(shù)結(jié)果。 在主函數(shù)中再打印一下x的值。
此結(jié)果執(zhí)行后如下:

如上代碼,我們傳入的是形參,在函數(shù)中修改形參是不會(huì)改變?cè)鹊闹档?,這是因?yàn)楹瘮?shù)運(yùn)行時(shí)候會(huì)先進(jìn)行壓棧,運(yùn)行過(guò)程中會(huì)產(chǎn)線局部信息等,恰恰好,我們傳入的形參就是該類(lèi)型的值,所以運(yùn)行后會(huì)出棧,出棧后函數(shù)所在的內(nèi)存也會(huì)被銷(xiāo)毀,所以函數(shù)內(nèi)的局部變量隨著出棧也被銷(xiāo)毀了。所以直接修改形參無(wú)效。
以上這個(gè)就是值傳遞。
那什么是引用傳遞呢?我們還是拿上面這個(gè)例子做比方,只不過(guò)傳遞的類(lèi)型換一下,從數(shù)值類(lèi)型更換為字典類(lèi)型,如:
def modify_x(dict):
dict["x"] = 99
print("數(shù)中修改過(guò)后的值:" , dict)
a={
"x":66
}
modify_x(a)
print("執(zhí)行modify_x函數(shù)后的值:", a)如上代碼,我們定義了一個(gè)字典a,該字典有一個(gè)key為x,值為66。在調(diào)用modify_x函數(shù)中,我們將a傳遞給了函數(shù),在函數(shù)中,我們將該字典key為x的賦值為99,函數(shù)結(jié)束,在主函數(shù)中打印a的值。
執(zhí)行后結(jié)果如下:

是不是感覺(jué)很詫異,同樣的代碼,為什么傳遞整形 和 傳遞 字典 , 所執(zhí)行的效果不一樣呢? 這是因?yàn)?code>python機(jī)制就是如此,它在傳遞該值的時(shí)候,使用的是指針傳遞,所以值沒(méi)有改變,我們將其稱之為引用傳遞。
可以干預(yù)參數(shù)傳遞是值傳遞還是引用傳遞么
python不可以干預(yù)參數(shù)傳遞的類(lèi)型,因?yàn)?code>python不像c、c++一樣,可以傳遞形參,也可以傳遞指針類(lèi)型。
在python中,參數(shù)傳遞是由解釋器實(shí)現(xiàn)的,所以說(shuō),普通開(kāi)發(fā)者,沒(méi)辦法直接干預(yù)參數(shù)傳遞方式,但是可以曲線救國(guó),善用return就是其中一條,例如我們將最開(kāi)始的代碼修改一下,不直接修改值,而是返回一個(gè)新的值,例如:
def modify_x(x):
x = 99
return x
x = 66
x = modify_x(x)
print("執(zhí)行modify_x函數(shù)后的值:" , x)我們執(zhí)行后,結(jié)果為:

這并不是修改x的值,而是接收modify_x傳遞回來(lái)的新值。
探尋一下值傳遞底層是如何實(shí)現(xiàn)的
我們之前所述的值傳遞,都是對(duì)數(shù)據(jù)的拷貝,可是現(xiàn)實(shí)真的如此么? 我們可以寫(xiě)一個(gè)案例來(lái)看下:
def modify_x(x):
print("函數(shù)中:",id(x))
x = 123
print("函數(shù)外:",id(x))
modify_x(x)在上述代碼中,有一個(gè)新的知識(shí)點(diǎn)是方法id,它可以查看變量的內(nèi)存地址。在上述例子中,在主函數(shù)中定義一個(gè)整形x,值為123,在傳遞給函數(shù)前,使用id方法查看一下變量的內(nèi)存地址。而后傳遞給函數(shù)modify_x,在該函數(shù)中,也使用id方法來(lái)查看一下形參x的地址。
若真如我們所猜想,那么2個(gè)內(nèi)存地址應(yīng)該不一致才對(duì),我們運(yùn)行下程序:

發(fā)現(xiàn)函數(shù)內(nèi),和函數(shù)外的地址都是一樣的? 哎,這是怎么回事呢?
這是因?yàn)樵?code>python中,解釋器為了優(yōu)化性能,避免大量無(wú)用數(shù)據(jù)拷貝,所以在傳遞的時(shí)候,一開(kāi)始全是傳遞的實(shí)參,只有當(dāng)函數(shù)內(nèi)修改了值后,才會(huì)新申請(qǐng)一個(gè)內(nèi)存來(lái)存該值。細(xì)節(jié)可以查看這個(gè)例子:
def modify_x(x) :
print("函數(shù)中1:",id(x))
x = 456
print("函數(shù)中2:",id(x))
x=123
print("函數(shù)外0:",id(x))
modify_x(x)上述代碼,我們?cè)?code>modify_x函數(shù)中,修改變量x前后都打印其內(nèi)存地址,結(jié)果如下:

我們發(fā)現(xiàn),在未修改之前,地址內(nèi)存都是指向同一個(gè)地址,修改之后,內(nèi)存地址也變了。
如果我們將x更換為引用傳遞的數(shù)據(jù)的話,就不會(huì)出現(xiàn)以下這種情況,可以看下面這個(gè)例子:
def modify x(x) :
print("函數(shù)中1:",id(x))
x[0] = 456
print("函數(shù)中2:",id(x))
x = [123]
print("函數(shù)外0:",id(x))
modify_x(x)
print("最后的值:" , x)上述代碼,我們做了一個(gè)小小的改動(dòng),我們將整形數(shù)據(jù)x,更改為了列表類(lèi)型,最后再打印一下x的值,查看變了沒(méi)有,代碼運(yùn)行結(jié)果如下:

發(fā)現(xiàn)內(nèi)存地址的值并沒(méi)有改變,且x的值在函數(shù)中真的被修改了。
所以通過(guò)上述例子,可以說(shuō)明,值傳遞的時(shí)候,再?zèng)]有修改的時(shí)候,該變量地址還是指向原來(lái)的地址,當(dāng)值被修改后,就會(huì)開(kāi)辟一個(gè)新的內(nèi)存地址用于存儲(chǔ)該值。這樣的話可以避免拷貝大量數(shù)據(jù)。
最后再總結(jié)一下,哪些類(lèi)型是引用傳遞,哪些類(lèi)型是值傳遞:
引用傳遞分別有 列表、字典、集合、自定義類(lèi)實(shí)例等。
值傳遞分別有 字符串類(lèi)型、元組、布爾類(lèi)型、數(shù)值類(lèi)型等。
總結(jié)
本篇文章簡(jiǎn)單介紹了值傳遞和引用傳遞,值傳遞,修改函數(shù)內(nèi)值后,不會(huì)影響原始值,而引用傳遞,修改函數(shù)內(nèi)值后,會(huì)印象到原始數(shù)據(jù)。不過(guò)有一個(gè)小細(xì)節(jié),就是值傳遞,若不進(jìn)行修改值的時(shí)候,其實(shí)內(nèi)存地址是指向的原始值的地址,當(dāng)修改值的時(shí)候,才會(huì)真正申請(qǐng)內(nèi)存來(lái)存儲(chǔ)修改的值,但是隨著函數(shù)出棧,該函數(shù)內(nèi)的數(shù)據(jù)局部變量,也會(huì)被銷(xiāo)毀。
到此這篇關(guān)于Python基礎(chǔ)之值傳遞和引用傳遞詳解的文章就介紹到這了,更多相關(guān)Python值傳遞 引用傳遞內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python中利用sqrt()方法進(jìn)行平方根計(jì)算的教程
這篇文章主要介紹了Python中利用sqrt()方法進(jìn)行平方根計(jì)算的教程,是Python學(xué)習(xí)的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-05-05
如何利用python將一個(gè)py文件變成一個(gè)軟件詳解
在我們完成一個(gè)Python項(xiàng)目或一個(gè)程序時(shí),希望將Python的py文件打包成在Windows系統(tǒng)下直接可以運(yùn)行的exe程序,下面這篇文章主要給大家介紹了關(guān)于如何利用python將一個(gè)py文件變成一個(gè)軟件的相關(guān)資料,需要的朋友可以參考下2023-04-04
TensorFlow中權(quán)重的隨機(jī)初始化的方法
本篇文章主要介紹了TensorFlow中權(quán)重的隨機(jī)初始化的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-02-02
python實(shí)現(xiàn)批量解析郵件并下載附件
這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)批量解析郵件并下載附件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-06-06
python讀取word 中指定位置的表格及表格數(shù)據(jù)
這篇文章主要介紹了python讀取word 中指定位置的表格及表格數(shù)據(jù),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2019-10-10
20行python代碼的入門(mén)級(jí)小游戲的詳解
這篇文章主要介紹了python入門(mén)級(jí)小游戲,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05
python 利用jieba.analyse進(jìn)行 關(guān)鍵詞提取
這篇文章主要介紹了python 利用jieba.analyse進(jìn)行關(guān)鍵詞提取的方法,幫助大家更好的利用python,感興趣的朋友可以了解下2020-12-12

