《Abaqus GUI程序开发指南(Python语言)》——2.5 动态类型简介
本節(jié)書摘來自異步社區(qū)《Abaqus GUI程序開發(fā)指南(Python語言)》一書中的第2章,第2.5節(jié),作者: 賈利勇 , 富琛陽子 , 賀高 , 周正光 更多章節(jié)內(nèi)容可以訪問云棲社區(qū)“異步社區(qū)”公眾號查看。
2.5 動態(tài)類型簡介
前面講述了Python中常用的數(shù)據(jù)類型,可以看出,在Python語言中使用變量時,都沒有聲明變量的存在以及類型,但變量還可以工作。這一點與靜態(tài)編譯語言C、C++或Java有很大的區(qū)別。這就是Python語言的動態(tài)類型模型。
在Python語言中,數(shù)據(jù)類型是在運行過程中自動決定的,而不是通過代碼聲明。變量在賦值的時候才被創(chuàng)建,它可以引用任何類型的對象,變量和對象分別存儲在內(nèi)存中的不同位置,兩者通過鏈接進行關(guān)聯(lián)。
對于下列代碼:
>>>a=5Python將會執(zhí)行3個不同的步驟去完成這個請求,這些步驟反映了Python語言中所有賦值的操作過程。
(1)創(chuàng)建一個新對象來代表數(shù)字5。
(2)創(chuàng)建一個變量a。
(3)將變量a與新對象a相關(guān)聯(lián)。
在Python中從變量到對象的鏈接稱作引用。也就是說,引用是一種關(guān)系,以內(nèi)存中的指針形式實現(xiàn)。一旦變量被使用(也就是被引用),Python自動跟隨這個變量到對象的鏈接。
2.5.1 類型的歸屬
在Python語言中,類型屬于對象,不屬于變量,我們可以對一個變量進行多次賦值,且允許每次賦值的類型不同,例如:
【實例2.20】單變量多次賦值
>>>a=5 #將變量a與整型對象關(guān)聯(lián) >>>a='five' #將變量a與字符串型對象關(guān)聯(lián) >>>a=5.0 #將變量a與浮點型對象關(guān)聯(lián)上述代碼中,變量a一開始是整型,然后變成一個字符串,最后變成了浮點數(shù)。這一點,在C語言中是無法理解的。但是在Python中,理解起來就很簡單,因為變量名根本沒有類型。實際上Python的變量就是在特定的時間引用了一個特定的對象,而對象是具有類型的,每個對象都包含了一個頭部信息,其中標(biāo)記了對象的類型。
可以看出,Python代碼比通常慣用的代碼更加靈活,如果能正確地使用Python,代碼能夠自動以多種類型進行工作。
2.5.2 垃圾回收機制
在實例2.20中,當(dāng)重新給變量a賦值時,它前一個引用對象是會發(fā)生變化的。在Python中,每當(dāng)一個變量名被賦予了一個新的對象時,且之前的那個對象沒有被其他變量名或?qū)ο笏玫脑?#xff0c;那么之前的那個對象占用的空間就會被回收,這種自動回收對象占用空間的技術(shù)叫作垃圾回收。
在Python內(nèi)部,垃圾回收是如何實現(xiàn)的呢?實際上,每個對象中都保持了一個計數(shù)器,計數(shù)器記錄了當(dāng)前指向該對象的引用次數(shù),也就是該對象被引用的次數(shù)。一旦這個計數(shù)器被設(shè)置為零,這個對象的內(nèi)存空間就會被自動回收。
垃圾回收最直接且可感受的好處就是,可以在腳本中任意使用該對象而不需要考慮釋放內(nèi)存空間。與C和C++這樣的底層語言相比,省去了大量基礎(chǔ)代碼。
2.5.3 共享引用及原處修改
首先看一個兩個變量的重復(fù)賦值實例。
【實例2.21】
>>> a=5 >>> b=a >>> a,b (5, 5)該實例中,第一行創(chuàng)建了對象5,并將變量a與之關(guān)聯(lián),第二行創(chuàng)建了變量b,變量b也成為對象5的一個引用。實際上,變量a和變量b都引用了相同的對象,都指向了相同的內(nèi)存空間,這在Python語言中叫作共享引用——多個變量名引用同一對象。
對上述代碼做如下修改:
>>> a=5 >>> b=a >>> a ='five' >>> a,b ('five', 5)第三行代碼創(chuàng)建了一個新的對象'five',并設(shè)置a對這個新的對象進行引用,而b仍然繼續(xù)引用之前的對象5。
與其他語言不同,在Python中,給一個變量賦一個新的值,并不是替換了原始的對象,而是重新創(chuàng)建一個不同的對象,并讓這個變量去引用這個新的對象。實際效果就是,對一個變量賦值,僅僅會影響被賦值的變量。
但是,也有一些特殊的情況,當(dāng)引用一些可變對象時,在原處對對象進行修改時,就會出現(xiàn)不一樣的情況。例如,在一個列表中對某一個偏移位置進行重新賦值時,會改變這個列表對象,而不是生成一個新的對象。首先看一個容易理解的實例:
【實例2.22】
>>> a=[1,2,3] >>> b=a >>> a [1, 2, 3] >>> b [1, 2, 3] >>> a=999 >>> a 999 >>> b [1, 2, 3]由程序執(zhí)行結(jié)果可以看出,上述實例中一開始變量a和b都引用了列表對象[1,2,3],后來當(dāng)對a重新賦值后,創(chuàng)建了新的對象999,并讓a引用了這個新的對象,整個過程中b并沒有發(fā)生變化,這與前面的實例類似,同屬于共享引用的范疇。
然而,列表中的元素都是通過其索引位置進行讀取的,例如:
>>> a=[1,2,3] >>> b=a >>> a[0],a[1],a[2] (1, 2, 3)其中,a[0]引用的是對象1,a[1]引用的是對象2,a[2]引用的是對象3。當(dāng)然,列表自身也是一個對象,接下來對上述代碼做一下簡單的修改,就會出現(xiàn)明顯不同的結(jié)果。
【實例2.23】
>>> a=[1,2,3] #創(chuàng)建列表對象[1,2,3]和變量a,并讓a引用該對象 >>> b=a #創(chuàng)建變量b,并讓b引用同一列表對象 >>> a [1, 2, 3] >>> b [1, 2, 3] #變量a和b數(shù)值相同 >>> a[0]='one' #修改變量所引用的對象的一個元素 >>> a ['one', 2, 3] #變量a數(shù)值發(fā)生變化 >>> b ['one', 2, 3] #變量b數(shù)值也發(fā)生變化在上述程序中,我們沒有改變a,只是改變了a所引用對象的一個元素,這類修改會覆蓋列表對象中的某些部分,它不僅僅會影響變量a,也會同時影響變量b,因為它們引用的是同一個列表對象。對于這種在原處修改的對象,共享引用時需要加倍小心,不注意的話非常容易出錯。
如果不希望上述情況出現(xiàn)時,需要使用Python的對象復(fù)制,而不是創(chuàng)建引用。Python有多種復(fù)制列表的方法,現(xiàn)列舉如下。
【實例2.24】列表對象復(fù)制
>>> a=[1,2,3] >>> b=a[:] #復(fù)制列表 >>> a [1, 2, 3] >>> b [1, 2, 3] >>> a[0]=999 >>> a [999, 2, 3] >>> b [1, 2, 3] #a引用的列表中某一元素變化時,b未改變。這種情況下,對a的修改不會影響b,因為b引用的是a所引用對象的復(fù)制,兩個變量指向了不同的內(nèi)存區(qū)域。需要注意的是,這種分片技術(shù)不能用于集合和字典等非序列類型的對象中。
除了上述復(fù)制方法之外,還可以使用copy()函數(shù)實現(xiàn),例如:
【實例2.25】copy()函數(shù)
>>> import copy >>> a=[1,2,3] >>> b=copy.copy(a) >>> b [1, 2, 3] >>> a[0]=999 >>> a [999, 2, 3] >>> b [1, 2, 3]另外,需要注意的是,copy()函數(shù)可以用于集合或者字典等無序的對象類型中。
**
2.5.4 共享引用和相等**
由于Python的引用機制,在Python程序中有兩種不同的方法去檢查兩個變量是否相等,以下面的共享引用來說明。
【實例2.26】
>>> a=[1,2,3] >>> b=a >>> a==b True >>> a is b True上述代碼中,第一種判斷方法是采用“==”操作符,測試兩個變量所引用的對象是否有相同的值。第二種方法“is”操作符,是檢查對象的同一性,如果兩個變量a和b均指向同一個對象,它會返回True,所以這是一種更嚴(yán)格的相等測試。如果兩個變量名引用的對象值相等,但是是不同的對象,那么在使用“is”操作符進行判斷時,它會返回False,例如:
【實例2.27】
>>> a=[1,2,3] >>> b=[1,2,3] >>> a==b True >>> a is b False上面的代碼中,第一行創(chuàng)建了一個列表對象[1,2,3]和變量a,并將變量a與之關(guān)聯(lián),第二行又創(chuàng)建了一個列表對象[1,2,3]和變量b,變量a和b引用的對象數(shù)值相同,卻不是同一個對象。
另外,需要特別注意的就是,當(dāng)我們對小的數(shù)字采用上述同樣的操作時,返回的結(jié)果會有所不同,例如:
【實例2.28】
>>> a=1 >>> b=1 >>> a==b True >>> a is b True為什么這組測試的結(jié)果和實例2.27測試的結(jié)果互相矛盾呢?原因就是,對于小的整數(shù)和字符串,Python會將其緩存并復(fù)用,所以在本實例中才會出現(xiàn)a和b引用的是同一個對象的現(xiàn)象。
如果讀者想弄清楚一個對象被引用的次數(shù)的話,可以使用sys模塊下的getrefcount函數(shù)來查詢一個對象被引用的次數(shù)。例如:
>>> import sys >>> sys.getrefcount(1) 1044 >>> sys.getrefcount(5) 91總結(jié)
以上是生活随笔為你收集整理的《Abaqus GUI程序开发指南(Python语言)》——2.5 动态类型简介的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《JavaScript忍者秘籍》——导读
- 下一篇: 《短文本数据理解(1)》一1.3 短文本