關於Python函式傳參是傳值還是傳引用

2021-10-05 14:35:00 字數 2261 閱讀 6180

事情的起因要從昨天說起,昨天寫了個函式,對傳入的df做一些計算,大概長這樣:

def

summary2_cal1

(df)

: df1 = df.groupby([.

..])

.agg(

) df[

'ctau']=

' ' df2 = df.groupby([.

..])

.agg(

) df_part1 = pd.concat(

[df1, df2]

,sort=

false

).reindex(index=[(

...)

]).fillna('')

return df_part1

呼叫之後發現傳入的df發生了改變,我馬上黑人問號,之前我一直認為函式傳參是傳值,於是我又立馬寫了個函式驗證我自以為是的觀點:

a =

1def

f(a)

: a+=

1print

(f'in funtion a = '

)f(a)

print

(f'out funtion a = '

)# output in funtion a = 2

# out funtion a = 1

嗯…沒問題嘛,我就記得是傳值啊,那為什麼上面的df會改變呢,哎,工作還多著呢,以後在研究。

今天開啟csdn就看到這篇文章正好講到我昨天的困惑,但他也不是原創,是翻譯的so上這個問題的第乙個答案,但為什麼我覺得第二個答案回答的更好呢?真的!下面我來稍微翻譯下他的答案吧。

a =

1a =

2

你會認為a是乙個儲存著值1的記憶體位址,接著第二句話把儲存的值更新到了2。然而在python 裡不是這麼執行的,a開始是乙個物件的引用,這個物件就是值1,(注意了啊,萬物皆物件),接著第二句話a被賦值成了物件2的引用。這兩個物件可能繼續同時存在即使a不再指向第乙個物件,實際上它們可以被程式中的任意數量的其他引用共享。

當你呼叫乙個函式並傳參時,會建立乙個新的引用指向傳入的物件,這個引用是與原來的引用的互不相干的,你不能更新這個引用來影響原來的引用。在這個例子裡:

def

__init__

(self)

: self.variable =

'original'

self.change(self.variable)

defchange

(self, var)

: var =

'changed'

self.variable是字串物件original的乙個引用,當你呼叫change時建立了它的第二個引用var,在函式裡面對var重新賦值成了另乙個字串changed的引用,但是這些和self.variable是不相干也不會改變的。

但是如果你傳入乙個可變物件,那就不一樣了。因為這兩個引用指向同乙個物件,任何對該物件的改變會同時作用在兩個地方。(也就是函式內外)

def

__init__

(self)

:

self.variable =

['original'

] self.change(self.variable)

defchange

(self, var)

: var[0]

='changed'

講到這裡,我昨天的困惑和矛盾也就解決了。第乙個例子裡傳入的dataframe是可變物件,在函式內對它的列進行賦值操作,會同時對函式內外產生影響。而第二個例子裡傳入的是數字,是不可變物件a+=1只作用於函式內的這個引用,對函式外的a不影響。

補充一些官方的解釋

python函式傳參是傳值還是傳引用?

首先還是應該科普下函式引數傳遞機制 傳值和傳引用是什麼意思?函式引數傳遞機制問題在本質上是呼叫函式 過程 和被呼叫函式 過程 在呼叫發生時進行通訊的方法問題。基本的引數傳遞機制有兩種 值傳遞和引用傳遞。值傳遞 passl by value 過程中,被調函式的形式引數作為被調函式的區域性變數處理,即在...

python函式傳參是傳值還是傳引用?

首先還是應該科普下函式引數傳遞機制,傳值和傳引用是什麼意思?函式引數傳遞機制問題在本質上是呼叫函式 過程 和被呼叫函式 過程 在呼叫發生時進行通訊的方法問題。基本的引數傳遞機制有兩種 值傳遞和引用傳遞。值傳遞 passl by value 過程中,被調函式的形式引數作為被調函式的區域性變數處理,即在...

python函式傳參是傳值還是傳引用?

首先還是應該科普下函式引數傳遞機制,傳值和傳引用是什麼意思?函式引數傳遞機制問題在本質上是呼叫函式 過程 和被呼叫函式 過程 在呼叫發生時進行通訊的方法問題。基本的引數傳遞機制有兩種 值傳遞和引用傳遞。值傳遞 passl by value 過程中,被調函式的形式引數作為被調函式的區域性變數處理,即在...