Python中變量的賦值“=”問(wèn)題

1.jpg

寫(xiě)在前面

python中的“變量”是一個(gè)可以被賦值的廣義對(duì)象,更確切地說(shuō)是“引用”,它僅僅只是一個(gè)標(biāo)簽,其作用就是將它與內(nèi)存中的某個(gè)實(shí)際對(duì)象(狹義對(duì)象)相聯(lián)系,從而通過(guò)操作這個(gè)標(biāo)簽來(lái)操作實(shí)際對(duì)象。

一個(gè)變量不能孤立存在,創(chuàng)立之時(shí)就必須將其指向內(nèi)存中的某個(gè)實(shí)際對(duì)象(即用‘=’操作),此時(shí)變量的類(lèi)型、內(nèi)存地址、值就是它指向?qū)ο蟮念?lèi)型、內(nèi)存地址、值。

一個(gè)變量本身不屬于任何一種數(shù)據(jù)類(lèi)型,python不會(huì)為一個(gè)變量分配內(nèi)存,同一個(gè)變量可以指向不同類(lèi)型的對(duì)象(例a=300,a='a', a=[300,'a'])。

Python通過(guò)引用計(jì)數(shù)機(jī)制實(shí)現(xiàn)自動(dòng)垃圾回收功能,Python內(nèi)存中的每個(gè)對(duì)象都有一個(gè)引用計(jì)數(shù)器,用于統(tǒng)計(jì)該對(duì)象還被哪些變量引用著。多一次引用,計(jì)數(shù)多一次,少一次引用,計(jì)數(shù)少一次。當(dāng)計(jì)數(shù)為零時(shí),Python會(huì)將該對(duì)象銷(xiāo)毀,回收內(nèi)存。

賦值操作,表面上是將“=”右邊的量的值賦給左邊的變量,但本質(zhì)上是將右邊的量對(duì)應(yīng)的內(nèi)存對(duì)象與左邊的變量相聯(lián)系的過(guò)程。見(jiàn)下例:

>>>a = 300

該賦值語(yǔ)句做了三件事:1)開(kāi)辟了一塊內(nèi)存(可用id(a)查看地址);2)將該內(nèi)存的值設(shè)為300;3)將變量a指向該內(nèi)存。在重新將a指向其他對(duì)象之前,a就一直指向該內(nèi)存,也就一直代表整數(shù)300。這里內(nèi)存中的300是狹義“對(duì)象”,是個(gè)實(shí)實(shí)在在存在的東西。

在賦值語(yǔ)句中,通常有兩種情況:
一種是將狹義對(duì)象賦值給變量,形如:“變量=對(duì)象”,例如a = 300、a = 'python cgx'、a = [1,2,3]、a = (1,2,3)等,這幾個(gè)賦值語(yǔ)句右邊都是實(shí)實(shí)在在的對(duì)象,是存在于內(nèi)存中的。
另一種是將變量賦值給變量,形如:“變量=變量”,例如b=a,右邊是一個(gè)已經(jīng)存在的變量,注意它只是個(gè)引用,是個(gè)標(biāo)簽,不是具體對(duì)象,但它肯定已經(jīng)指向某個(gè)真實(shí)的對(duì)象了,否則a是不能存在的。
這兩種情況在python中有很大的不同,下面分別詳細(xì)討論。

(一)變量=對(duì)象,對(duì)象賦值給變量的情況

對(duì)于這種形式,我們也分兩種情況討論:

(1)賦值時(shí),待賦值“對(duì)象”在內(nèi)存中不存在

這種情況非常簡(jiǎn)單,遵循三步驟:開(kāi)辟內(nèi)存,指定內(nèi)存對(duì)應(yīng)的值,將其與變量相聯(lián)系。如下:

>>>a = 300 #int
>>>b = 'python cgx' #string
>>>c = [1,2,3] #list
>>>d = (1,2,3) #tuple
>>>e = {'age':25} #字典

(2)賦值時(shí),值相同的“對(duì)象”在內(nèi)存中已經(jīng)存在至少一個(gè)

對(duì)于這種情況稍微復(fù)雜,必須根據(jù)具體數(shù)據(jù)類(lèi)型分別進(jìn)行討論:

1)int,整型

>>>a = 1 
>>>b = 1
>>>id(a) #1598778384
>>>id(b) #1598778384

上例中a和b的指向的內(nèi)存地址都是1598778384,說(shuō)明在執(zhí)行b=1時(shí),并沒(méi)有重新開(kāi)辟內(nèi)存,而是將變量b也指向已經(jīng)存在的對(duì)象1上。但千萬(wàn)不要認(rèn)為所有的int情況都一樣,比如:

>>>a = 300 
>>>b = 300
>>>id(a) #96391536
>>>id(b) #96391664

根據(jù)前一個(gè)例子的經(jīng)驗(yàn),這里a和b兩個(gè)變量都指向?qū)ο?00,因此id(a)和id(b)應(yīng)該相同才對(duì),然而實(shí)際上兩者卻是不同的,這是什么情況?到底哪些整數(shù)會(huì)相同,哪些會(huì)不同呢?為了解決這一問(wèn)題,我們做如下實(shí)驗(yàn)

>>>for i in range(-1000,1000):
          a = i #直接將i賦給a
          b = int(i.__str__()) #先將i轉(zhuǎn)化為字符串再轉(zhuǎn)化為int,以區(qū)別將同值但新的i賦給b
         if a is b: #判斷a和b的地址是否相同
                print(i)
-5
-4
-3
……
255
256

上述代碼的目的是查看到底哪些整數(shù)會(huì)共享內(nèi)存,從結(jié)果可以看出從-5開(kāi)始到256結(jié)束,共262個(gè)整數(shù)會(huì)共享內(nèi)存。這真是神奇的存在,特別是為啥負(fù)整數(shù)只到-5。這個(gè)問(wèn)題暫時(shí)先不去深究。
python之所以這么干,是因?yàn)檫@些小的整數(shù)在編程時(shí)出現(xiàn)的頻率非常高,如果不停地都生成銷(xiāo)毀生成銷(xiāo)毀,會(huì)使計(jì)算效率降低,為了減少這種操作,干脆就將所有重復(fù)創(chuàng)建小整數(shù)的情況都統(tǒng)統(tǒng)指向同一個(gè)已經(jīng)存在的小整數(shù)上,只要還有一個(gè)變量連接到該小整數(shù),他就不會(huì)被銷(xiāo)毀。而且int數(shù)據(jù)是不可變對(duì)象,因此該小整數(shù)一旦在內(nèi)存中被創(chuàng)建,就會(huì)一直存在,直到?jīng)]有變量指向他才被銷(xiāo)毀。
對(duì)于浮點(diǎn)數(shù)則不存在這種情況。

2)string,字符串型

字符串的情況跟int有點(diǎn)類(lèi)似,對(duì)于短字符串(沒(méi)有空格)和空字符串('')而言,共享內(nèi)存;對(duì)于長(zhǎng)字符串(有空格)而言,不共享內(nèi)存。

>>>a = '' #空字符串
>>>b = ''
>>>id(a) #3504816
>>>id(b) #3504816

>>>a = 'sssssssssssssssssssssssssssssssss' #沒(méi)空格,短字符串
>>>b = 'sssssssssssssssssssssssssssssssss' 
>>>id(a) #96397424
>>>id(b) #96397424

>>>a = 's s' #有空格,長(zhǎng)字符串
>>>b = 's s' 
>>>id(a) #96387624
>>>id(b) #96388856

3)list,列表型

對(duì)于列表而言,比較簡(jiǎn)單,每次都開(kāi)辟新的內(nèi)存,生成新的對(duì)象,包括空列表[]。如下:

>>>a = [] #空列表
>>>b = []
>>>id(a) #96384072
>>>id(b) #96384264

>>>a = [1] #短列表
>>>b = [1]
>>>id(a) #41856328
>>>id(b) #41877640

>>>a = list(range(10000)) #長(zhǎng)列表
>>>b = list(range(10000))
>>>id(a) #41880840
>>>id(b) #41880904

4)tuple,元組型

對(duì)于元組而言,每次都開(kāi)辟新的內(nèi)存,生成新的對(duì)象;但是對(duì)于空元組(),則共享內(nèi)存。如下:

>>>a = () #空元組
>>>b = ()
>>>id(a) #3342408
>>>id(b) #3342408

>>>a = (1,) #短元組
>>>b = (1,)
>>>id(a) #37476560
>>>id(b) #37702512

>>>a = tuple(range(10000)) #長(zhǎng)元組
>>>b = tuple(range(10000))
>>>id(a) #40619720
>>>id(b) #40699784

4)dict,字典型

對(duì)于字典而言,比較簡(jiǎn)單,每次都開(kāi)辟新的內(nèi)存,生成新的對(duì)象,包括空字典{}。如下:

>>>a = {} #空字典
>>>b = {}
>>>id(a) #34237752
>>>id(b) #34237824

>>>a = {'x':1} #短字典
>>>b = {'x':1}
>>>id(a) #5467448
>>>id(b) #5467520

>>>a = dict(enumerate(range(10000))) #長(zhǎng)字典
>>>b = dict(enumerate(range(10000)))
>>>id(a) #41778560
>>>id(b) #41778632

(二)變量B=變量A,變量賦值給變量的情況

對(duì)于變量A對(duì)變量B賦值的情況(變量A必然已經(jīng)指向某個(gè)內(nèi)存對(duì)象了),無(wú)論哪種數(shù)據(jù)類(lèi)型,無(wú)論長(zhǎng)短復(fù)雜簡(jiǎn)單,都只有一個(gè)結(jié)果,即兩個(gè)變量都指向相同的內(nèi)存單元。這里用int舉例, 其他情況不再贅述。

>>>a = 1 #簡(jiǎn)短整數(shù),-5~256
>>>b = a
>>>id(a) #1598778384
>>>id(b) #1598778384

>>>a = 300 #復(fù)雜整數(shù)
>>>b = a
>>>id(a) #33205968
>>>id(b) #33205968
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 包(lib)、模塊(module) 在Python中,存在包和模塊兩個(gè)常見(jiàn)概念。 模塊:編寫(xiě)Python代碼的py...
    清清子衿木子水心閱讀 3,908評(píng)論 0 27
  • 一、快捷鍵 ctr+b 執(zhí)行ctr+/ 單行注釋ctr+c ...
    o_8319閱讀 6,031評(píng)論 2 16
  • 1 實(shí)現(xiàn)通過(guò)線程池執(zhí)行任務(wù) 創(chuàng)建了一個(gè)ThreadPoolExecutor,參數(shù)中使用了默認(rèn)的線程創(chuàng)建工廠Defa...
    冷冷DerFan閱讀 476評(píng)論 0 1
  • 表弟來(lái)家跟老爹喝了酒 喝多了老爹說(shuō)想他老爹抹眼淚了 20年左右了吧 我也是第一次見(jiàn)老爹如此
    鬼懿閱讀 161評(píng)論 0 0
  • 我寫(xiě)作業(yè)太磨蹭,每天都要寫(xiě)到十一二點(diǎn),寫(xiě)作業(yè)太糊弄了,我要把這個(gè)錯(cuò)誤改掉。承諾人:陳盈佳
    陳盈佳閱讀 394評(píng)論 0 0

友情鏈接更多精彩內(nèi)容