python3高级语法:__slots__属性、property装饰器、上下文管理协议、__new__方法
#practice29:派生內(nèi)置不可變類型并修改其實(shí)例化行為(以tuple為例)
__new__() is intended mainly to allow subclasses of immutable types (like int, str, or tuple) to customize instance creation.
__init__()Called after the instance has been created (by __new__()), but before it is returned to the caller.
__new__() and __init__() work together in constructing objects (__new__() to create it, and __init__() to customize it)
- 修改內(nèi)置不可變類型(int/str/tuple)的實(shí)例化行為,做法是:繼承內(nèi)置不可變類,并覆蓋其new方法。
- 注意:并非所有內(nèi)置類都可以簡單繼承,list/dir/str繼承后重新覆蓋的某些內(nèi)置方法會(huì)不起作用,即新類還會(huì)調(diào)用覆蓋前的內(nèi)置方法;為保證不會(huì)發(fā)生這種情況,最好去繼承collections.UserDict/collections.UserList/collections.String
- new負(fù)責(zé)創(chuàng)建對象,包含創(chuàng)建其大部分內(nèi)置方法、屬性等;init負(fù)責(zé)個(gè)性化定制(初始化)對象,即將init的參數(shù)賦值為對象屬性!
1、定制化tuple類型
必須重新定義new與init
class IntTuple(tuple):#覆蓋tuple的內(nèi)置靜態(tài)方法,不需要加裝飾器def __new__(cls,iterable):g = (x for x in iterable if isinstance(x,int) and x > 0)return super(IntTuple,cls).__new__(cls,g)#參數(shù)iterable必須要有,這是數(shù)據(jù)入口,隨后該數(shù)據(jù)會(huì)被傳遞給__new__def __init__(self,iterable):print(self)#可選super(IntTuple,self).__init__()a = IntTuple([1,44,'2',(3,5)])#practice30:減小實(shí)例內(nèi)存開銷
- 類屬性slots用于申明實(shí)例的所有屬性。
- dict屬性用于保存對象的所有屬性,并可以動(dòng)態(tài)添加
- 在類屬性slots中排除dict屬性,即可禁止對象動(dòng)態(tài)添加屬性!如:obj.qq = 100,則對象有了新屬性qq
1、 定義類屬性slots對實(shí)例屬性的影響
import sys class A():def __init__(self,id,name):self.id = idself.name = nameclass B():__slots__ = ['id','name']def __init__(self,id,name):self.id = idself.name = name print(dir(A(1,'lisi'))) print(dir(B(2,'lisi'))) print(set(dir(A(2,'lisi'))) - set(dir(B(2,'lisi')))) print(sys.getsizeof(A(1,'lisi'))) print(sys.getsizeof(A(1,'lisi').__dict__))屬性差異為紅色標(biāo)記的兩個(gè)屬性,weakref對于內(nèi)存的消耗可不計(jì)
practice31:讓對象支持上下文管理器
- 實(shí)現(xiàn)上下文管理協(xié)議主要依賴類的實(shí)例方法enter與exit
- 句法 with obj as obj1: pass ,實(shí)際執(zhí)行過程為obj調(diào)用enter方法,返回的新對象賦值給obj1,之后執(zhí)行塊內(nèi)代碼,最后obj1執(zhí)行exit方法!
1、實(shí)例
mydict = {}class A():def __init__(self,a,b):self.a = aself.b = bdef __enter__(self):mydict['a'] = self.amydict['b'] = self.b#后三個(gè)參數(shù)是固定的,異常類型,異常實(shí)例、異常traceback對象def __exit__(self,exc_type,exc_val,exc_tb):mydict.clear()print(mydict) with A(3,5) as Q:print(mydict) print(mydict)2、異常捕獲與壓制
mydict = {}class A():def __init__(self,a,b):self.a = aself.b = bdef __enter__(self):mydict['a'] = self.amydict['b'] = self.b#后三個(gè)參數(shù)是固定的,異常類型,異常實(shí)例、異常traceback對象def __exit__(self,exc_type,exc_val,exc_tb):#對于with代碼塊中出現(xiàn)的異常,__exit__能捕獲print(exc_type,exc_val,exc_tb)mydict.clear()#返回True能成功壓制異常!!!return Trueprint(mydict) with A(3,5) as Q:raise Exception('myerror')print(mydict) print(mydict)with代碼塊產(chǎn)生異常,但任然會(huì)執(zhí)行exit方法,清空字典;這是上下文管理器的默認(rèn)行為方式,即先執(zhí)行exit后再拋出代碼塊內(nèi)的異常,確保exit方法始終要執(zhí)行
通過return True成功壓制異常,即有異常發(fā)生也不拋出!
#practice32:可管理的對象屬性
- 直接訪問對象屬性的形式,如:obj.x = ‘1’,這種方式調(diào)用簡單,但卻不夠靈活,例如想要檢查屬性x的值必須為int,此種方法顯然不合適;此外存在安全性問題,如上述賦值后x為str,如果后續(xù)進(jìn)行數(shù)學(xué)運(yùn)算,會(huì)拋出異常,在程序復(fù)雜的情況下很難查找!
使用setx/getx方法來訪問屬性,相當(dāng)于中間抽象出一層,進(jìn)行一些邏輯處理,比較靈活,但每次調(diào)用起來比較費(fèi)勁
解決方法:內(nèi)置裝飾器property
總結(jié)
以上是生活随笔為你收集整理的python3高级语法:__slots__属性、property装饰器、上下文管理协议、__new__方法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 完美解决Flask-Migrate使用S
- 下一篇: 最常用git命令汇总(参考列表)