Python代碼提升及代碼精簡(jiǎn)教程_第1頁
Python代碼提升及代碼精簡(jiǎn)教程_第2頁
Python代碼提升及代碼精簡(jiǎn)教程_第3頁
Python代碼提升及代碼精簡(jiǎn)教程_第4頁
Python代碼提升及代碼精簡(jiǎn)教程_第5頁
已閱讀5頁,還剩3頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、Diet在小型程序中,特別是在腳本中,使用 Python 自帶的diet來表示結(jié)構(gòu)信息非常簡(jiǎn)單方便:>>> ob = 'x':1, 'y':2, 'z':3>>> x = ob'x'>>> ob'y' = y由于在Python 3.6 中diet的實(shí)現(xiàn)采用了一組有序鍵,因此其結(jié)構(gòu)更為緊湊,更深得人心。但是,讓我們看看diet在內(nèi)容中占用的空間大?。?gt;>> print(sys.getsizeof(ob)240如上所示,diet 占用了大量?jī)?nèi)存,尤

2、其是如果突然虛需要?jiǎng)?chuàng)建大量實(shí)例時(shí):實(shí)例數(shù)對(duì)象大小1 000 000240 Mb10 000 0002.40 Gb100 000 00024 Gb類實(shí)例有些人希望將所有東西都封裝到類中,他們更喜歡將結(jié)構(gòu)定義為可以通過屬性名訪問的類:elass Point:#def _init_(self, x, y, z):self.x = xself.y = yself.z = z>>> ob = Point(1,2,3)>>> x = ob.x>>> ob.y = y類實(shí)例的結(jié)構(gòu)很有趣:字段大小(比特)PyGC_Head24PyObjeet_HEAD16

3、_weakref_8_diet_8合計(jì):56在上表中,_weakref_是該列表的引用,稱之為到該對(duì)象的弱引用( weakreference );字段 diet是該類的實(shí)例字典的引用,其中包含實(shí)例屬性的值(注意在64-bit 引用平臺(tái)中占用 8字節(jié))。從 Python 3.3 開始,所有類實(shí)例的字典的鍵都存儲(chǔ)在共享空間中。這樣就減少了內(nèi)存中實(shí)例的大 小:>>> print(sys.getsizeof(ob), sys.getsizeof(ob._diet )56 112因此,大量類實(shí)例在內(nèi)存中占用的空間少于常規(guī)字典( diet ):實(shí)例數(shù)大小1 000 000168 Mb10

4、 000 0001.68 Gb100 000 00016.8 Gb不難看出,由于實(shí)例的字典很大,所以實(shí)例依然占用了大量?jī)?nèi)存。帶有slots_的類實(shí)例為了大幅降低內(nèi)存中類實(shí)例的大小,我們可以考慮干掉 _diet_ 和_weakref_ 。為此,我們可以借助_slots_:class Point:_slots_ = 'x', 'y', 'z'def _init_(self, x, y, z):self.x = xself.y = yself.z = z>>> ob = Point(1,2,3)>>> print(s

5、ys.getsizeof(ob)64如此一來,內(nèi)存中的對(duì)象就明顯變小了:字段大小(比特)PyGC_Head24PyObject_HEAD16x8y8z8總計(jì):64在類的定義中使用了slots以后,大量實(shí)例占據(jù)的內(nèi)存就明顯減少了:實(shí)例數(shù)大小1 000 00064 Mb10 000 000640 Mb100 000 0006.4 Gb目前,這是降低類實(shí)例占用內(nèi)存的主要方式。這種方式減少內(nèi)存的原理為: 在內(nèi)存中,對(duì)象的標(biāo)題后面存儲(chǔ)的是對(duì)象的引用(即屬性值),訪問這些屬 性值可以使用類字典中的特殊描述符:>>> pprint(Point._diet ) mappingproxy(&#

6、39;x':member 'x' of 'Point' objects,'y':member 'y' of 'Point' objects,'z':member 'z' of 'Point' objects)為了自動(dòng)化使用slots創(chuàng)建類的過重,你可以使用庫namedlist 。dlist函數(shù)可以創(chuàng)建帶有_slots_的類:>>> Point = namedlist('Point', ('x

7、', 'y', 'z')還有一個(gè)包attrs ,無論使用或不使用_slots_都可以利用這個(gè)包自動(dòng)創(chuàng)建類。元組Python 還有一個(gè)自帶的元組(tuple )類型,代表不可修改的數(shù)據(jù)結(jié)構(gòu)。元 組是固定的結(jié)構(gòu)或記錄,但它不包含字段名稱。你可以利用字段索引訪問元 組的字段。在創(chuàng)建元組實(shí)例時(shí),元組的字段會(huì)一次性關(guān)聯(lián)到值對(duì)象:> >> ob = (1,2,3)> >> x = ob0> >> ob1 = y # ERROR元組實(shí)例非常緊湊:> >> print(sys.getsizeof(o

8、b)72由于內(nèi)存中的元組還包含字段數(shù),因此需要占據(jù)內(nèi)存的8個(gè)字節(jié),多于帶有_slots_的類:字段大小(字節(jié))PyGC_Head24PyObject_HEAD16ob_size8081828總計(jì):72命名元組由于元組的使用非常廣泛,所以終有一天你需要通過名稱訪問元組。為了滿足這種需求,你可以使用模塊dtuple 。 namedtuple 函數(shù)可以自動(dòng)生成這種類:>>> Point = namedtuple('Point', ('x', 'y', 'z')如上代碼創(chuàng)建了元組的子類,其

9、中還定義了通過名稱訪問字段的描述符。對(duì)于上述示例,訪問方式如下:class Point(tuple):#propertydef _get_x(self):return self0propertydef _get_y(self):return self1propertydef _get_z(self):return self2#def _new_(cls, x, y, z):return tuple._new_(cls, (x, y, z)這種類所有的實(shí)例所占用的內(nèi)存與元組完全相同。但大量的實(shí)例占用的內(nèi)存也會(huì)稍稍多一些:實(shí)例數(shù)大小1 000 00072 Mb10 000 000720 Mb100

10、 000 0007.2 Gb記錄類:不帶循環(huán) GC的可變更命名元組由于元組及其相應(yīng)的命名元組類能夠生成不可修改的對(duì)象,因此類似于ob.x的對(duì)象值不能再被賦予其他值,所以有時(shí)還需要可修改的命名元組。由 于Python沒有相當(dāng)于元組且支持賦值的內(nèi)置類型,因此人們想了許多辦法。在這里我們討論一下記錄類( recordclass ,),它在 StackoverFlow 上廣受 好評(píng)。此外,它還可以將對(duì)象占用的內(nèi)存量減少到與元組對(duì)象差不多的水平。recordclass 包弓I入了類型 recordclass.mutabletuple ,它幾乎等價(jià)于元組,但 它支持賦值。它會(huì)創(chuàng)建幾乎與namedtuple

11、完全一致的子類,但支持給屬性賦新值(而不需要?jiǎng)?chuàng)建新的實(shí)例)。 recordclass函數(shù)與namedtuple函數(shù)類 似,可以自動(dòng)創(chuàng)建這些類:>>> Point = recordclass('Point', ('x', 'y', 'z')>>> ob = Point(1,2, 3)類實(shí)例的結(jié)構(gòu)也類似于tuple ,但沒有PyGC_Head :字段大小(字節(jié))PyObject_HEAD16ob_size8x8y8z8總計(jì):48在默認(rèn)情況下,recordclass函數(shù)會(huì)創(chuàng)建一個(gè)類,該類不參與垃圾回收

12、機(jī)制。一般來說,namedtuple 和recordclass都可以生成表示記錄或簡(jiǎn)單數(shù)據(jù)結(jié)構(gòu)(即非遞歸結(jié)構(gòu))的類。在 Python中正確使用這二者不會(huì)造成循環(huán)引用。因此,recordclass生成的類實(shí)例默認(rèn)情況下不包含PyGC_Head片段(這個(gè)片段是支持循環(huán)垃圾回收機(jī)制的必需字段,或者更準(zhǔn)確地說,在創(chuàng)還類的PyTypeObject結(jié)構(gòu)中,flags字段默認(rèn)情況下不會(huì)設(shè)置Py_TPFLAGS_HAVE_GC標(biāo)志)。大量實(shí)例占用的內(nèi)存量要小于帶有_slots_的類實(shí)例:實(shí)例數(shù)大小1 000 00048 Mb10 000 000480 Mb100 000 0004.8 Gbdataobject

13、recordclass 庫提出的另一個(gè)解決方案的基本想法為:內(nèi)存結(jié)構(gòu)采用與帶_slots_ 的類實(shí)例同樣的結(jié)構(gòu),但不參與循環(huán)垃圾回收機(jī)制。這種類可以通過 recordclass.make_dataclass函數(shù)生成:>>> Point = make_dataclass('Point', ('x', 'y', 'z')這種方式創(chuàng)建的類斯認(rèn)會(huì)生成可修改的實(shí)例。另一種方法是從recordclass.dataobject 繼承:class Point(dataobject):x:inty:intz:int這種方法創(chuàng)建的類

14、實(shí)例不會(huì)參與循環(huán)垃圾回收機(jī)制。內(nèi)存中實(shí)例的結(jié)構(gòu)與帶 有_slots_的類相同,但沒有 PyGC_Head :字段大小(字節(jié))PyObject_HEAD16ob_size8x8y8z8總計(jì):48>>> ob = Point(1,2,3)>>> print(sys.getsizeof(ob)40如果想訪問字段,則需要使用特殊的描述符來表示從對(duì)象開頭算起的偏移量, 其位置位于類字典內(nèi):mappingproxy(_new_': <staticmethod at 0x7f203c4e6be0,'x': <recordclass.da

15、taobject.datas10tgetset at 0x7f203c55c690>,'y': <recordclass.dataobject.datas10tgetset at 0x7f203c55c670,'z': <recordclass.dataobject.datas10tgetset at 0x7f203c55c410>)大量實(shí)例占用的內(nèi)存量在CPython 實(shí)現(xiàn)中是最小的:Cython還有一個(gè)基于 Cython (/ )的方案。該方案的優(yōu)點(diǎn)是字段可 以使用C語言的原子類型。訪問字段的描述符可

16、以通過純Python 創(chuàng)建。例如:cdef class Python:cdef public int x, y, zdef _init_(self, x, y, z): self.x = xself.y = yself.z = z本例中實(shí)例占用的內(nèi)存更小:>>> ob = Point(1,2,3)>>> print(sys.getsizeof(ob)32內(nèi)存結(jié)構(gòu)如下:字段PyObject_HEAD大小(字節(jié))16x4y4z4nycto4總計(jì):32大量副本所占用的內(nèi)存量也很小:實(shí)例數(shù)大小1 000 00032 Mb10 000 000320 Mb100 000 0003.2 Gb但是,需要記住在從 Python代碼訪問時(shí),每次訪問都會(huì)引發(fā)int 類型和Python 對(duì)象之間的轉(zhuǎn)換。Numpy使用擁有大量數(shù)據(jù)的多維數(shù)組或記錄數(shù)組會(huì)占用大量?jī)?nèi)存。但是,為了有效地利用純Python 處理數(shù)據(jù),你應(yīng)該使用Numpy包提供的函數(shù)。>>> Point = numpy.dtype('x', 32), ('y', 32), ('z', 32)一個(gè)擁有N個(gè)元素、初始化成零的數(shù)組可以通過下面的函數(shù)創(chuàng)建

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論