Python 中,以雙下劃線__
包起來的方法,統(tǒng)稱為:魔術(shù)方法(Magic Method)
魔術(shù)方法是一個類或?qū)ο笾械奶厥夥椒?,和普通方法的區(qū)別在于,普通方法需要手動調(diào)用,而魔術(shù)方法是在特定時刻自動觸發(fā)執(zhí)行的
如果希望根據(jù)自己的程序定制自己特殊功能的類,那么就需要對這些魔術(shù)方法進行重寫
1. __new__
(1). 說明:實例化對象方法
(2). 觸發(fā)時機:在實例化時觸發(fā)
(3). 參數(shù):至少得有一個
cls
接收當前類,寫法為__new__(cls, *args, **kwargs)
(4). 返回值:必須使用
return
關(guān)鍵字返回一個對象實例(5). 作用:實例化(創(chuàng)建)對象,開辟內(nèi)存地址空間對象并返回
(6). 注意:實例化對象是
Object
類底層實現(xiàn),其他類繼承了Object
的__new__
才能夠?qū)崿F(xiàn)實例化對象
2. __init__
(1). 說明:初始化方法,相當于
java中的構(gòu)造方法
,在__new__
執(zhí)行后被調(diào)用(2). 觸發(fā)時機:初始化對象時觸發(fā)(區(qū)別于
__new__
實例化時的觸發(fā))(3). 參數(shù):至少得有一個
self
接收__new__
方法返回的對象,寫法為__init__(self, name, age)
(4). 返回值:無
(5). 作用:初始化對象的成員
(6). 注意:使用該方式初始化的成員都是直接寫入對象當中,類中無法具有
3. __del__
(1). 說明:析構(gòu)魔術(shù)方法
(2). 觸發(fā)時機:當一塊地址空間沒有任何指針引用的時候被觸發(fā)
在 Python 解釋器中,當所有代碼程序執(zhí)行完成則會進行垃圾回收,也叫內(nèi)存釋放,這時就會觸發(fā)
__del__
方法使用
del 對象名
顯示刪除引用關(guān)系時,如果此操作將某塊地址空間的最后一個引用關(guān)系給刪除,則會觸發(fā)__del__
方法(3). 參數(shù):僅只一個
self
參數(shù)接收對象(4). 返回值:無
(5). 作用:使用完對象時回收資源,沒有指針引用的時候會調(diào)用,絕大多數(shù)時候不需要重寫
(6). 注意:
del 對象名
不一定會觸發(fā)當前方法,只有某塊地址空間無任何引用時才會觸發(fā)
4. __call__
(1). 說明:調(diào)用對象函數(shù)的魔術(shù)方法
(2). 觸發(fā)時機:將對象當作函數(shù)調(diào)用時觸發(fā),使用形式為
對象名稱()
,會默認調(diào)用__call__
函數(shù)里的內(nèi)容(3). 參數(shù):至少得有一個
self
接收對象,剩余參數(shù)根據(jù)調(diào)用時傳入的參數(shù)決定,寫法為__call__(self, args)
(4). 返回值:根據(jù)具體重寫邏輯而定
(5). 作用:將復(fù)雜的步驟統(tǒng)一放在該函數(shù)內(nèi)實現(xiàn),減少調(diào)用的步驟,比較方便
(6). 注意:無
5. __str__
(1). 說明:當
print(對象名)
時想看到更多的信息時,可以重寫__str__
方法,將想要輸出的信息放在__str__
函數(shù)中返回(2). 觸發(fā)時機:使用
print(對象名)
或者str(對象名)
的時候觸發(fā)(3). 參數(shù):一個
self
參數(shù)接收對象(4). 返回值:必須是字符串類型
(5). 作用:
print(對象名)
時可以自定義輸出更多有用信息(6). 注意:無
class People: # 類名Person后面加不加(Object)效果是一樣的,都表示繼承自O(shè)bject類
# 創(chuàng)建對象
def __new__(cls, *args, **kwargs):
print('調(diào)用__new__構(gòu)造方法')
position = super().__new__(cls) # 調(diào)用父類的__new__()方法創(chuàng)建對象,開辟內(nèi)存空間
# print(position) # <__main__.People object at 0x7fa19b8a6c10>
return position # 將創(chuàng)建的地址空間對象返回,交給__init__方法接收
# 實例化對象
def __init__(self, name, age):
self.name = name # 在__new__方法返回的內(nèi)存空間地址中放置name屬性
self.age = age # 在__new__方法返回的內(nèi)存空間地址中放置age屬性
# print(self) # <__main__.People object at 0x7fa19b8a6c10>
print('調(diào)用__init__初始化方法')
# 對象作為函數(shù)調(diào)用時的邏輯
def __call__(self, args):
print('調(diào)用__call__方法,接收到的參數(shù)為:%s' % args)
# 刪除對象: 在(del 對象名后所對應(yīng)的地址空間無任何引用時)或者程序執(zhí)行結(jié)束之后
def __del__(self):
print('調(diào)用__del__析構(gòu)方法,刪除對象,釋放內(nèi)存空間')
# 自定義print(對象名)時的輸出內(nèi)容
def __str__(self):
return '對象的name是:' + self.name + ',對象的age是:' + str(self.age)
if __name__ == '__main__':
p = People('liuming', 20)
# print(p) # <__main__.People object at 0x7fa19b8a6c10>
p('abc') # 調(diào)用__call__方法
p1 = p
p2 = p
p3 = p # 截止到這里p對象所在的地址空間,共有4個對象都在引用,分別是對象:p,p1,p2,p3
del p3 # 刪除的是p3對內(nèi)存地址空間的引用關(guān)系,此時p對象所在的地址空間,共有3個對象在引用,分別是對象:p,p1,p2
del p2
del p1
del p # 自動調(diào)用__del__方法,因為p對象所在的地址空間已經(jīng)沒有任何對象在引用了,所以需要對內(nèi)存地址進行回收釋放
p4 = People('xiaohong', 18)
print(p4) # 對象的name是:xiaohong,對象的age是:18---注意:此時輸出的不再是地址空間值了,而是__str__函數(shù)自定義return的內(nèi)容
print(str(p4)) # 輸出內(nèi)容同print(p4)
1.調(diào)用__new__構(gòu)造方法
2.調(diào)用__init__初始化方法
3.調(diào)用__call__方法,接收到的參數(shù)為:abc
4.調(diào)用__del__析構(gòu)方法,刪除對象,釋放內(nèi)存空間
5.調(diào)用__new__構(gòu)造方法
6.調(diào)用__init__初始化方法
7.對象的name是:xiaohong,對象的age是:18
8.對象的name是:xiaohong,對象的age是:18
9.調(diào)用__del__析構(gòu)方法,刪除對象,釋放內(nèi)存空間
p = People('liuming', 20)
與p4 = People('xiaohong', 18)
該代碼塊執(zhí)行時都會自動調(diào)用__new__
與__init__
函數(shù),對應(yīng)結(jié)果輸出為:第1,2,5,6行
p('abc')
該代碼塊執(zhí)行時會自動調(diào)用__call__
函數(shù),對應(yīng)結(jié)果輸出為:第3行
del p
該代碼塊執(zhí)行時會自動調(diào)用__del__
函數(shù),對應(yīng)結(jié)果輸出為:第4行
注意:當執(zhí)行代碼塊del p3/p2/p1
時都沒有自動調(diào)用__del__
函數(shù)
是因為此時p對象
所指向的地址空間還有p這個對象
在引用,指針引用關(guān)系還存在
直到del p
執(zhí)行時才將該地址空間唯一的指針引用關(guān)系給銷毀了,所以就調(diào)用了__del__
函數(shù)
print(p4)
與print(str(p4))
該代碼塊執(zhí)行時會自動調(diào)用__str__
函數(shù),對應(yīng)結(jié)果輸出為:第7,8行
所有代碼塊全部執(zhí)行完畢后,Python解釋器的垃圾回收機制會將分配的內(nèi)存進行釋放回收,此時也會調(diào)用__del__
函數(shù),對應(yīng)結(jié)果輸出為:第9行
end
聯(lián)系客服