最新文章專題視頻專題問答1問答10問答100問答1000問答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
當(dāng)前位置: 首頁 - 科技 - 知識百科 - 正文

Python類方法__init__和__del__構(gòu)造、析構(gòu)過程分析

來源:懂視網(wǎng) 責(zé)編:小采 時間:2020-11-27 14:40:15
文檔

Python類方法__init__和__del__構(gòu)造、析構(gòu)過程分析

Python類方法__init__和__del__構(gòu)造、析構(gòu)過程分析:最近學(xué)習(xí)《Python參考手冊》學(xué)到Class部分,遇到了類的構(gòu)造析構(gòu)部分的問題: 1、什么時候構(gòu)造? 2、什么時候析構(gòu)? 3、成員變量如何處理? 4、Python中的共享成員函數(shù)如何訪問? ------------------------ 探索過程: 1、經(jīng)過查找,Python中沒有專用
推薦度:
導(dǎo)讀Python類方法__init__和__del__構(gòu)造、析構(gòu)過程分析:最近學(xué)習(xí)《Python參考手冊》學(xué)到Class部分,遇到了類的構(gòu)造析構(gòu)部分的問題: 1、什么時候構(gòu)造? 2、什么時候析構(gòu)? 3、成員變量如何處理? 4、Python中的共享成員函數(shù)如何訪問? ------------------------ 探索過程: 1、經(jīng)過查找,Python中沒有專用

最近學(xué)習(xí)《Python參考手冊》學(xué)到Class部分,遇到了類的構(gòu)造析構(gòu)部分的問題:

1、什么時候構(gòu)造?
2、什么時候析構(gòu)?
3、成員變量如何處理?
4、Python中的共享成員函數(shù)如何訪問?
------------------------
探索過程:
1、經(jīng)過查找,Python中沒有專用的構(gòu)造和析構(gòu)函數(shù),但是一般可以在__init__和__del__分別完成初始化和刪除操作,可用這個替代構(gòu)造和析構(gòu)。還有一個__new__用來定制類的創(chuàng)建過程,不過需要一定的配置,此處不做討論。
2、類的成員函數(shù)默認都相當(dāng)于是public的,但是默認開頭為__的為私有變量,雖然是私有,但是我們還可以通過一定的手段訪問到,即Python不存在真正的私有變量。如:

代碼如下:


__priValue = 0 # 會自動變形為"_類名__priValue"的成員變量

3、由于Python的特殊性,全局成員變量是共享的,所以類的實例不會為它專門分配內(nèi)容空間,類似于static,具體使用參看下面的例子。

測試1:

代碼如下:


# encoding:utf8

class NewClass(object):
num_count = 0 # 所有的實例都共享此變量,即不單獨為每個實例分配
def __init__(self,name):
self.name = name
NewClass.num_count += 1
print name,NewClass.num_count
def __del__(self):
NewClass.num_count -= 1
print "Del",self.name,NewClass.num_count
def test():
print "aa"

aa = NewClass("Hello")
bb = NewClass("World")
cc = NewClass("aaaa")

print "Over"

調(diào)試運行:

代碼如下:


Hello 1
World 2
aaaa 3
Over
DeException l Hello 2
AttributeError: "'NoneType' object has no attribute 'num_count'" in > ignored
Exception AttributeError: "'NoneType' object has no attribute 'num_count'" in > ignored


我們發(fā)現(xiàn),num_count 是全局的,當(dāng)每創(chuàng)建一個實例,__init__()被調(diào)用,num_count 的值增一,當(dāng)程序結(jié)束后,所有的實例會被析構(gòu),即調(diào)用__del__() 但是此時引發(fā)了異常。查看異常為 “NoneType” 即 析構(gòu)時NewClass 已經(jīng)被垃圾回收,所以會產(chǎn)生這樣的異常。

但是,疑問來了?為什么會這樣?按照C/C++等語言的經(jīng)驗,不應(yīng)該這樣啊!經(jīng)過查找資料,發(fā)現(xiàn):

Python的垃圾回收過程與常用語言的不一樣,Python按照字典順序進行垃圾回收,而不是按照創(chuàng)建順序進行。所以當(dāng)系統(tǒng)進行回收資源時,會按照類名A-Za-z的順序,依次進行,我們無法掌控這里的流程。

明白這些,我們做如下嘗試:

代碼如下:


# encoding:utf8

class NewClass(object):
num_count = 0 # 所有的實例都共享此變量,即不單獨為每個實例分配
def __init__(self,name):
self.name = name
NewClass.num_count += 1
print name,NewClass.num_count
def __del__(self):
NewClass.num_count -= 1
print "Del",self.name,NewClass.num_count
def test():
print "aa"

aa = NewClass("Hello")
bb = NewClass("World")
cc = NewClass("aaaa")

del aa
del bb
del cc

print "Over"

調(diào)試輸出:

代碼如下:


Hello 1
World 2
aaaa 3
Del Hello 2
Del World 1
Del aaaa 0
Over

OK,一切按照我們預(yù)料的順序發(fā)生。
但是,我們總不能每次都手動回收吧?這么做Python自己的垃圾回收還有什么意義?

SO,繼續(xù)查找,我們還可以通過self.__class__訪問到類本身,然后再訪問自身的共享成員變量,即 self.__class__.num_count , 將類中的NewClass.num_count替換為self.__class__.num_count 編譯運行,如下:

代碼如下:


# encoding:utf8

class NewClass(object):
num_count = 0 # 所有的實例都共享此變量,即不單獨為每個實例分配
def __init__(self,name):
self.name = name
self.__class__.num_count += 1
print name,NewClass.num_count
def __del__(self):
self.__class__.num_count -= 1
print "Del",self.name,self.__class__.num_count
def test():
print "aa"

aa = NewClass("Hello")
bb = NewClass("World")
cc = NewClass("aaaa")

print "Over"

結(jié)果:

代碼如下:


Hello 1
World 2
aaaa 3
Over
Del Hello 2
Del World 1
Del aaaa 0

Perfect!我們完美地處理了這個問題!

PS:

書上又提到了一些問題,在這里作補充(僅作為參考):

__new__()是唯一在實例創(chuàng)建之前執(zhí)行的方法,一般用在定義元類時使用。

del xxx 不會主動調(diào)用__del__方法,只有引用計數(shù)==0時,__del__()才會被執(zhí)行,并且定義了__del_()的實例無法被Python的循環(huán)垃圾收集器收集,所以盡量不要自定義__del__()。一般情況下,__del__() 不會破壞垃圾處理器。

實驗中發(fā)現(xiàn)垃圾回收自動調(diào)用了__del__, 這與書上所說又不符,不知是什么原因,需要繼續(xù)學(xué)習(xí)。

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文檔

Python類方法__init__和__del__構(gòu)造、析構(gòu)過程分析

Python類方法__init__和__del__構(gòu)造、析構(gòu)過程分析:最近學(xué)習(xí)《Python參考手冊》學(xué)到Class部分,遇到了類的構(gòu)造析構(gòu)部分的問題: 1、什么時候構(gòu)造? 2、什么時候析構(gòu)? 3、成員變量如何處理? 4、Python中的共享成員函數(shù)如何訪問? ------------------------ 探索過程: 1、經(jīng)過查找,Python中沒有專用
推薦度:
  • 熱門焦點

最新推薦

猜你喜歡

熱門推薦

專題
Top