一、先來兩段代碼!
a = 100def beyond(num):num+=numprint(num)beyond(a)#結果為:200
print(a)#結果為:100
a = 100def beyond(num):num=num+numprint(num)beyond(a)#結果為:200
print(a)#結果為:100
通過這兩段代碼的結果可以看出,最終的結果和大家想的完全一樣。
但事實這兩段代碼是完全等價的嘛?答案是否定的,要是是完全一樣我寫這篇博客閑著沒事干哈。
廢話不多說,下面進入正題。
在Python中列表
、字典
是可變數據類型;可變數據類型在定義字典的時候是不可以當key的,可以當value,因為key有個hash過程。
如果一個變量指向一個全局變量,那么想要修改這個全局變量,就得看下這個全局變量是不是可變數據類型。以這兩段代碼為例,a=100,這里變量a指向全局變量100,需要修改100,得看下100這個整型數是不是可變數據類型。很顯然,不是!
分析一下程序執行過程:
①a = 100 #先定義一個內存空間1存儲100,變量a指向這個列表1
②def beyond(num): #程序運行到這里時,系統已明確這個函數需要有一個參數,由于Python是動態語言(第四部分中有解釋),故此時尚未清楚這個函數具體實現的功能是什么。
③beyond(a) #這里變量a指向誰,也會將函數中形參num也指向誰,這里均指向內存空間1
④當程序運行到函數beyond(num)時,:
- 若num+=num #其實遇到
+=
是有兩個過程要完成
1,首先判斷能否對這個num值進行修改,即判斷num是否是可變數據類型;若能修改直接在num上修改
2,若不能修改則需要重新定義一個變量,讓這個變量再重新指向這個值;即系統會重新定義內存空間2,用來存放num+num的值。即此時的num指向內存空間2,內存空間2存放num+num的值。 - 若num=num+num #遇到
=
直接重新定義一個變量,讓這個變量再重新指向這個值;即系統會重新定義內存空間2,用來存放num+num的值。即此時的num指向內存空間2,內存空間2存放num+num的值。
⑤print(num)
⑥print(a)
若為num = num + num 即先算等號右邊,會的到一個臨時的答案,得到這個臨時的答案相當于在內存中額外開辟了一塊內存;等號左邊則會指向這個額外開辟內存而已,所以a所指向的那塊地方沒有任何的變化,只不過在函數里面發生了變化,而在函數外面a的值并未發生任何變化。
到這里是不是有那么一點略懂了?哈哈哈,來繼續深入一點!
二、再來兩段代碼!
a = [100]def beyond(num):num+=numprint(num)beyond(a)#結果為:[100, 100]
print(a)#結果為:[100, 100]
上述代碼,很明顯,遇到num+=num,其實說白了直接看+=
就行,遇到+=
先判斷num是否可以修改,很顯然,a指向列表1,存放[100],列表是可變數據類型,直接再列表1中進行了修改,a指向列表1,num指向列表1,而指向+=
操作的時候是直接針對的列表1操作的,故a和num的最終值都是已經改變之后的值,即[100,100]。
a = [100]def beyond(num):num=num+numprint(num)beyond(a)#結果為:[100, 100]
print(a)#結果為:[100]
而這段代碼,a = [100],系統會為列表100分配內存空間,變量a會指向這個內存空間;接著是是num=num+num,系統會重新分配一個新的內存空間,存放num+num運算結果,num最終指向這個新的內存空間。a所指向的內存空間存放列表[100],而num指向的新的內存空間存放的是num+num的結果即[100,100]。這些輸出結果就可想而知了吧~
總結:num+=num并不等價于num=num+num,若是數字,答案是一樣的,但是真正的原理并不相同。因為Python語言當中,并不是值賦值,而是引用。所有的只要牽涉到等號,統統都是引用,
好了,到此結束,是不是有那么一丟丟感覺了?