python常用的魔法方法(雙下劃線)
前言
本文介紹一下python中常用的魔法方法以及面向?qū)ο笾蟹浅V匾膯卫J健?br />
魔法方法
python中一切皆對象,因為python是面向?qū)ο蟮木幊陶Z言。python給類和對象提供了大量的內(nèi)置方法,這些內(nèi)置方法也稱魔法方法。這些魔法方法總是在某種條件下自動觸發(fā)執(zhí)行,就像魔法一樣。
__init__方法
該方法是用來接收定義類時類中__new__方法返回的空對象后為空對象進行初始化的操作,沒有返回值。
class Test(): def __init__(self, name): self.name = name def test(self): print(self.name) t = Test('xu') t1 = Test('python')
__new__方法
該方法是當類被調(diào)用實例化對象時首先被觸發(fā)的方法,用來實例化一個空對象并返回。
class Test(): def __new__(cls,*args, **kwargs): return object.__new__(cls, *args, **kwargs) def __init__(self, name): self.name = name
__call__方法
如果想讓一個對象變成一個可調(diào)用對象(加括號可以調(diào)用),需要在該對象的類中定義__call__方法,調(diào)用可調(diào)用對象的返回值就是__call__方法的返回值。
class Test(): def __init__(self): self.name = 'python' def __call__(self, *args, **kwargs): # self是Test類的對象 print(self) # <__main__.Test object at 0x000001C78CE78FD0> print(self.name) t = Test() t() # python
__str___方法
當對象被訪問打印時觸發(fā)執(zhí)行,該方法必須有一個字符串類型的返回值。
class Test(): def __init__(self, name): self.name = name def __str__(self): return self.name t = Test('xu') print(t1) # xu
__del___方法
__del__方法是在對象被刪除時自動觸發(fā),由于python的垃圾回收機制會自動清理程序中沒用的資源,因此如果一個對象只是占用應(yīng)用程序的資源,沒有必要定義__del__方法,但是如果設(shè)計到占用系統(tǒng)資源的話比如打開的文件對象,由于關(guān)系到操作系統(tǒng)的資源,python的垃圾回收機制派不上用場的時候,就需要為對象創(chuàng)建__del__方法,用于對象被刪除后自動觸發(fā)回收操作系統(tǒng)資源。
class Test: def __init__(self): self.x = open('a.txt',mode='w') # self.x = 占用的是操作系統(tǒng)資源 def __del__(self): print('run') # 發(fā)起系統(tǒng)調(diào)用,告訴操作系統(tǒng)回收相關(guān)的系統(tǒng)資源 self.x.close() obj = T() del obj # obj.__del__()
__enter__ & __exit__方法
使用with上下文管理時,會觸發(fā)對象中的__enter__方法,并將__enter__方法的返回值賦值給as聲明的變量。
with語句正常結(jié)束的時候會觸發(fā)__exit__方法,該方法的三個參數(shù)分別代表異常類型、異常值和溯源信息,如果with語句代碼塊出現(xiàn)異常,則with語句后的代碼都不會被執(zhí)行,但是如果該方法返回值為True,異常會被清空,with代碼塊后的代碼還會被正常執(zhí)行。代碼如下:
class Open: def __init__(self): self.name = 'open' def __enter__(self): print('with語句執(zhí)行時會首先執(zhí)行的方法,返回值會賦值給as聲明的變量') return self.name def __exit__(self, exc_type, exc_val, exc_tb): print('with中的代碼塊執(zhí)行完畢時執(zhí)行exit') print(exc_type, '如果出現(xiàn)異常表示異常類型') print(exc_val, '表示異常的值') print(exc_tb, '表示異常的溯源信息') return 123 # 非零 非空 非None為真 with Open() as test: print(test) raise TypeError('看一下錯誤信息') print('我會不會被執(zhí)行呢') # 當__exit__方法返回值為真時,會被執(zhí)行,否則不會被執(zhí)行
item系列方法
item系列方法包括__setitem__、__getitem__、delitem__方法,這三種方法分別會在中括號賦值/修改值、中括號取值、中括號刪除值時觸發(fā),比如可以自定義一個字典類,并自定義中括號賦值、取值、刪除值的方法:
class MyDict(dict): def __setitem__(self, key, value): print('執(zhí)行setitem', key, value) # 執(zhí)行setitem, x, 1 self.__dict__[key] = value def __getitem__(self, item): print('執(zhí)行g(shù)etitem', item) # 執(zhí)行g(shù)etitem x print(self.__dict__[item]) # 1 def __delitem__(self, key): print('執(zhí)行delitem', key) # 執(zhí)行delitem x self.__dict__.pop(key) d = MyDict() d['x'] = 1 print(d['x']) del d['x']
attr系列方法
attr系列方法包括__setattr__,__getattr__,__delattr__,__setattr__在添加/修改屬性時會觸發(fā),___delattr__刪除屬性的時候觸發(fā),__getattr__在使用.調(diào)用屬性并且屬性不存在時觸發(fā)。如下代碼所示
class Test: def __init__(self): self.name = 'python' def __setattr__(self, key, value): print('添加/修改屬性setattr') self.__dict__[key] = value # self.key = value # 會出現(xiàn)無線遞歸,因為對象.屬性會調(diào)用__setattr__方法 def __delattr__(self, item): print('刪除屬性delattr') self.__dict__.pop(item) def __getattr__(self, item): print('屬性不存在時調(diào)用getattr') t = Test() t.x = 'x' print(t.y) del t.x
單例模式
單例模式是一種軟件設(shè)計模式,為了保證一個類無論調(diào)用多少次產(chǎn)生的對象都指向同一個內(nèi)存地址,即僅僅只有一個對象。
實現(xiàn)單例模式的方式有很多,總的原則就是保證一個類只要實例化一個對象,因此關(guān)鍵點就是如何判斷這個類是否實例化過一個對象。
這里介紹幾種實現(xiàn)方式,供大家參考:
模塊導(dǎo)入的方式
這種方式的原理是模塊導(dǎo)入后只運行一次,后面再次使用該模塊中的類是直接從內(nèi)存中查找。
# cls_singleton.py class Foo(object): pass instance = Foo() # test.py import cls_singleton obj1 = cls_singleton.instance obj2 = cls_singleton.instance print(obj1 is obj2) # True
通過__new__方法
原理就是判斷類是否有實力,有就直接返回,沒有就保存到_instance中
class Test: _instance = None def __init__(self, name, age): self.name = name self.age = age def __new__(cls, *args, **kwargs): # if cls._instance: # return cls._instance # 有實例則直接返回 # else: # cls._instance = super().__new__(cls) # 沒有實例則new一個并保存 # return cls._instance # 這個返回是給是給init,再實例化一次,也沒有關(guān)系 if not cls._instance: # 這是簡化的寫法,上面注釋的寫法更容易提現(xiàn)判斷思路 cls._instance = super().__new__(cls) return cls._instance t1 = Test('python', 18) t2 = Test('python1', 18) print(t1 is t2) # True
自定義元類的方式
這種方式的原理是類調(diào)用的過程,類定義時會調(diào)用元類下的__init__,類調(diào)用(實例化對象)時會觸發(fā)元類下的__call__方法。
class Mymeta(type): def __init__(cls, name, bases, dic): super().__init__(name, bases, dic) cls._instance = None # 將記錄類的實例對象的數(shù)據(jù)屬性放在元類中自動定義了 def __call__(cls, *args, **kwargs): # 此call會在類被調(diào)用(即實例化時觸發(fā)) if cls._instance: # 判斷類有沒有實例化對象 return cls._instance else: # 沒有實例化對象時,控制類造空對象并初始化 obj = cls.__new__(cls, *args, **kwargs) obj.__init__(*args, **kwargs) cls._instance = obj # 保存對象,下一次再實例化可以直接返回而不用再造對象 return obj class Test(metaclass=Mymeta): def __init__(self, name, age): self.name = name self.age = age t1 = Test('python', 18) t2 = Test('python1', 18) print(t1 is t2) # True
結(jié)語
到此這篇關(guān)于python常用的魔法方法(雙下劃線)的文章就介紹到這了,更多相關(guān)python 魔法方法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python使用PyGreSQL操作PostgreSQL數(shù)據(jù)庫教程
這篇文章主要介紹了Python使用PyGreSQL操作PostgreSQL數(shù)據(jù)庫,需要的朋友可以參考下2014-07-07Pycharm打印大數(shù)據(jù)文件顯示不全的解決方法
這篇文章主要介紹了Pycharm打印大數(shù)據(jù)文件顯示不全的解決方法,昨晚寫了個小爬蟲,簡單分析下發(fā)現(xiàn)可以修改請求的url,直接獲取所有目標的數(shù)據(jù),想先打印在控制臺看看,發(fā)現(xiàn)打印的數(shù)據(jù)不全,所以本文記錄了一下解決方法,需要的朋友可以參考下2024-03-03對django views中 request, response的常用操作詳解
今天小編就為大家分享一篇對django views中 request, response的常用操作詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-07-07