轉(zhuǎn)載請注明: TheViper http://m.survivalescaperooms.com/TheViper
變量,對象和引用
在python中,類型是在運(yùn)行過程中自動(dòng)決定的,而不是通過代碼聲明。這意味著沒有必要事先聲明變量。
a=3解析的過程:
總之,變量在賦值的時(shí)候才創(chuàng)建,它可以引用任何類型的對象,并且必須在引用前賦值。
上面的代碼的賦值操作:

如上圖所示,變量和對象保存在內(nèi)存的不同部分,它們通過連接相關(guān)聯(lián)(圖中箭頭)。
具體的,在運(yùn)行a=3后,變量a變成對象3的一個(gè)引用。在內(nèi)部,變量事實(shí)上是到對象內(nèi)存空間(通過運(yùn)行常量表達(dá)式3創(chuàng)建)的一個(gè)指針。
以具體的術(shù)語來講,
事實(shí)上,python并不是對創(chuàng)建的所有對象都會重新申請新的一塊內(nèi)存空間。作為一種優(yōu)化,python會緩存不變的對象(如數(shù)值較小的數(shù)字,字符串,元組等)并對其進(jìn)行復(fù)用。
類型屬于對象,而不是變量
a=3a='viper'a=1.333
變量a剛開始是整數(shù),然后是字符串,最后是浮點(diǎn)數(shù),但是這段代碼可以運(yùn)行。這是因?yàn)椋趐ython中,情況很簡單,變量名沒有類型。
上面的代碼,我們只是把變量a修改為對不同對象的引用,從而讓變量a引用了不同類型的對象而已。
共享引用
a=3b=a
可以看到變量a,b引用了同一個(gè)對象。這時(shí),讓變量a引用另一個(gè)對象。
a=3b=aa='viper'

a='viper'創(chuàng)建了一個(gè)新的對象‘viper’,并讓變量a對這個(gè)新對象引用,而變量b仍然引用原來的對象3.所以這時(shí)變量b的值是3.
共享引用和在原處修改
有一些對象和操作確實(shí)會在原處改變對象,例如,在一個(gè)列表中對一個(gè)偏移賦值就會改變這個(gè)列表對象,而不是生成一個(gè)新的列表對象。對于這種可以在原處修改的對象,共享引用的時(shí)候要小心,因?yàn)閷σ粋€(gè)變量名的修改會影響其他和它引用同一對象的變量。
L1=[1,2,3]L2=L1L1[0]=33
這時(shí)變量L1,L2的值都會變成[33,2,3].
這種行為通常不是我們想要的,但是這種行為是默認(rèn)的,如果不想這種行為發(fā)生,就需要拷貝對象,而不是創(chuàng)建引用。
L1=[1,2,3]L2=L1[:]L1[0]='viper'PRint(L2)# [1,2,3]
因?yàn)長2引用的是L1引用對象的一個(gè)拷貝,這里兩個(gè)變量指向不同的內(nèi)存區(qū)域。所以L1的改變不會影響L2.
注意上面用到了分片,其他的有些可變的核心類型(如字典,集合)不能分片,這時(shí)就使用copy()方法。
共享對象和相等
由于python的引用模型,在python程序中有兩種不同的方法檢查是否相等。==和is
==檢查兩個(gè)被引用的對象是否擁有相同的值,這種方法被用作相等的檢查。
is會比較實(shí)現(xiàn)引用的指針,是檢測共享引用的一種方法。如果變量的引用值相等,但是是不同的對象,那is就返回false.比如,

變量M和L雖然值相同,但它們兩個(gè)不同的對象,在不同的內(nèi)存區(qū)域。
另外

這個(gè)驗(yàn)證了前面說的 python會緩存不變的對象(如數(shù)值較小的數(shù)字,字符串,元組等)并對其進(jìn)行復(fù)用。y=3只是讓變量y引用已經(jīng)創(chuàng)建的對象3.
新聞熱點(diǎn)
疑難解答
圖片精選