Python之各種內置方法
1、attr 系列
class foo: def __init__(self,NAME): self.name=NAME def __setattr__(self, key, value): # 作用:可以對 value 進行類型限制 if not isinstance(value,str): # 對 value 限制只能是字符串 raise TypeError(‘must be str‘) # print(‘setattr----key:%s,value:%s‘%(key,value))View Code# print(type(key)) # key 是字符串類型 # print(type(value)) # self.key=value # key 是字符串類型,self.屬性,屬性不能為字符串類型,不能這樣賦值 # setattr(self,key,value) # 跟上面一樣 self.key=valuse 會觸發 setattr 的執行,會造成遞歸 self.__dict__[key]=value # 直接在對象的 dict 字典裏面操作 def __delattr__(self, item):print(‘delattr:%s‘%item) # del self.__dict__[item] # 同樣,刪除直接去刪除對象的字典,法1 self.__dict__.pop(item) # 法2 def __getattr__(self, item): print(‘getattr:%s‘%item) f1=foo(‘egon‘) # f1.name=‘egon‘ 賦值操作會先觸發setattr 的執行 f1.age=‘18‘ del f1.age print(f1.__dict__) getattr 單獨拿出來class foo: def __init__(self, NAME): self.name = NAME # 只有屬性不存在才會觸發 getattr 的執行 def __getattr__(self, item): print(‘getattr:%s %s‘ % (item,type(item))) f1 = foo(‘egon‘) # f1.name=‘egon‘ 賦值操作會先觸發setattr 的執行 # print(f1.name) print(f1.xxxx) # 屬性不存在才會觸發 getattr 的執行
2、item 系列
__setitem__(self,key,value):當對類中的某個屬性進行"賦值"時觸發的函數(只有使用字典賦值的方式時才會觸發此方法的執行) 與Attr系列的區分:__setattr__(self):是在對象打點兒的方式賦值時,才會觸發的方法 class Foo: def __setitem__(self, key, value): print(key,"獲得",value) f = Foo() f["name"] = "egon" value = egon__setitem__
__delitem__(self,key):當類中的某個屬性被刪除時,觸發此方法(只有使用del字典方式刪除屬性時,才會觸發此方法) 與Attr系列的區分:__delattr__(self):使用del類打點兒屬性的方式刪除屬性,才會觸發此方法 class Foo: name = "egon" def __delitem__(self, key): print(key,"已被刪除") f = Foo() del f["name"]__delitem__
__getitem__(self,item):當調用類中的屬性或方法時觸發此方法的執行(只在使用類[key]字典的方式調用時,才會觸發此方法) 與Attr系列的區分:其實這裏已經很明顯了,__getattr__(self):是類打點兒調用且命名空間沒有發現名字的情況下,觸發此方法 class Foo: name = "egon" def __getitem__(self, item): print(item,"已被調用") f = Foo() f["name"]__getitem__
3、__slost__
__slost__:其實就是將類中的名稱鎖定,實例化對象,只可以賦值和調用,不可以刪除屬性和增加新的屬性
應用場景:當實例化幾萬個對象的時候,每個對象都會生成一個名稱空間__dict__,而每一個名稱空間都會各自占用一個內存,造成內存的浪費,用 __slost__,不用再產生 dict 了,省內存,對象的 dict 都統一用類的 dict,屬性都是用 slost 給定義的
class Foo: __slots__ = ["x","y"]#在類中定義屬性x和y f = Foo()#實例化Foo f.x = 1#此時我們可以使用實例化對象調用類中的屬性x f.y = 2 #如果現在,我們在實例化對象中增加一個z f.z = 3 #會得到如下錯誤 #AttributeError: ‘Foo‘ object has no attribute ‘z‘ #也就是不可以,對實例化對象增加新的屬性 #如果現在,我們在實例化對象中刪除一個x del f.x#此時程序執行並不會出錯,但是我們打印一下Foo的命名空間 print(Foo.__dict__) #{‘__doc__‘: None, ‘y‘: <member ‘y‘ of ‘Foo‘ objects>, ‘__module__‘: ‘__main__‘, ‘x‘: <member ‘x‘ of ‘Foo‘ objects>, ‘__slots__‘: [‘x‘, ‘y‘]} #依然可以看到x的存在,所以,實例化對象不可以刪除__slots__定義的屬性例1
class Foo: __slots__ = ["x","y"] Foo.__slots__ = "z" print(Foo.__dict__) #{‘__doc__‘: None, ‘x‘: <member ‘x‘ of ‘Foo‘ objects>, ‘__slots__‘: ‘z‘, ‘__module__‘: ‘__main__‘, ‘y‘: <member ‘y‘ of ‘Foo‘ objects>} del Foo.x print(Foo.__dict__) #{‘__doc__‘: None, ‘__slots__‘: ‘z‘, ‘__module__‘: ‘__main__‘, ‘y‘: <member ‘y‘ of ‘Foo‘ objects>} # f.z=3 對象也無法賦值 __slots__只是針對實例化對象的禁錮,直接對類中的屬性進行修改,是可以的例2
4、__next__ 和 __iter__
class foo: def __init__(self,start): self.start=start def __next__(self): return self def __iter__(self): n=self.start self.start=+1 return self f=foo(0) print(next(f)) # f.__next__() print(next(f)) # f.__next__() for i in f: # 執行 i=f.__iter__ 方法,轉化為一個叠代器 print(i) # next(i) 執行 next 方法View Code
5、__del__
這個是在回收實例化對象時觸發執行的方法
每當 del 實例化對象時會觸發
或者是程序結束時,會觸發,總之就是實例化對象失效時都會執行__del__方法
註:此方法一般無須定義,因為Python是一門高級語言,程序員在使用時無需關心內存的分配和釋放,因為此工作都是交給Python解釋器來執行,所以,析構函數的調用是由解釋器在進行垃圾回收時自動觸發執行的
class Foo: def __del__(self): print(self,"被釋放掉了") f = Foo() print(f) del f import time class Open: def __init__(self,file,mode=‘r‘,encoding=‘utf8‘): self.x=open(file,mode=mode,encoding=encoding) self.file=file self.mode=mode self.encoding=encoding def write(self): pass def __del__(self): print(‘del‘) self.x.close() # Open(‘a.txt‘,‘w‘) 需要開辟一個內存空間來存放值,產生一個對象,變量 f 與它進行綁定,此時 f 在引用,引用計數不為0 # 當引用計數為 0 的時候,就去對象裏面找 析構函數 del f=Open(‘a.txt‘,‘w‘) # 當跑完程序,f 與Open 的綁定關系就解除,觸發 del 的執行,回收值的內存 del f # 下面程序還沒跑完,就執行 del,刪除 f ,Open 沒有被引用,引用計數為 0 ,回收 Open time.sleep(1000) # 註意,如果沒有 del 方法,對象被刪除後,不會被立即回收,python回收機制會定期去回收View Code
6、__str__
class Pepole: def __init__(self,name,age): self.name=name self.age=age def __str__(self): # return ‘abc‘ # __str__ 方法必須返回字符串 obj=Pepole(‘egon‘,18) print(obj) # 當打印對象的時候觸發 __str__方法View Code
7、__enter__和__exit__
所謂上下文管理協議,就是咱們打開文件時常用的一種方法:with
__enter__(self):當with開始運行的時候觸發此方法的運行
__exit__(self, exc_type, exc_val, exc_tb):當with運行結束之後觸發此方法的運行
exc_type如果拋出異常,這裏獲取異常的類型
exc_val如果拋出異常,這裏顯示異常內容
exc_tb如果拋出異常,這裏顯示所在位置
用途或者說好處:
1.使用with語句的目的就是把代碼塊放入with中執行,with結束後,自動完成清理工作,無須手動幹預
2.在需要管理一些資源比如文件,網絡連接和鎖的編程環境中,可以在__exit__中定制自動釋放資源的機制,你無須再去關系這個問題,這將大有用處
class Foo: def __enter__(self): print(‘=======================》enter‘) return 111111111111111 def __exit__(self, exc_type, exc_val, exc_tb): print(‘exit‘) print(‘exc_type‘,exc_type) print(‘exc_val‘,exc_val) print(‘exc_tb‘,exc_tb) return True # 如果不加這一行,表示抓到報錯,整個程序退出,不再往下執行 # 如果__exit()返回值為True,那麽異常會被清空,就好像啥都沒發生一樣,with後的語句正常執行 # with Foo(): #res=Foo().__enter__() # pass with Foo() as obj: #res=Foo().__enter__() #obj=res print(‘with foo的自代碼塊‘,obj) raise NameError(‘名字沒有定義‘) # with語句中代碼塊出現異常,則with後的代碼都無法執行 print(‘************************************‘) # 執行與否,看 exit 返回的是否 true print(‘1111111111111111111111111111111111111111‘)例1
class Open: def __init__(self,file,mode=‘r‘,encoding=‘utf8‘): # 使用系統函數open()傳入相應打開文件所需的參數,將文件句柄傳遞給self.f self.f=open(file,mode=mode,encoding=encoding) def __enter__(self): return self # 這裏要返回 self 而不是 self.f,self.f 是調用真實的 open 文件操作的方法 # 這裏 self 調用的是 Open 類裏面的各個函數屬性 def __exit__(self, exc_type, exc_val, exc_tb): self.f.close() print(‘關閉‘) def write(self,line): #自己定義write方法 print(‘ok‘) self.f.write(line) #使用self.f 文件句柄 write 方法將內容寫入文件 # 利用__getattr__(),Attr系列中的getattr,當對象沒有找到Open中傳遞過來的名字時,調用此方法 def __getattr__(self, item): return getattr(self,item) # 返回self.f 文件句柄中,被對象調用,且不在Open類中的名字 with Open(‘a.txt‘,‘w‘,encoding=‘utf8‘) as obj: # obj=Open(‘a.txt‘,‘w‘,encoding=‘utf8‘) obj.write(‘123‘) # 調用的是類裏面的 write 方法,方法裏面有 obj.f.write 調用真實的 write例2
8、__doc__
描述信息用的
class Foo: ‘我是描述信息‘ pass print(Foo.__doc__) class Foo: ‘我是描述信息‘ pass class Bar(Foo): pass print(Bar.__doc__) #該屬性無法繼承給子類 該屬性無法被繼承View Code
9、__call__
對象後面加括號,觸發執行。
註:構造方法的執行是由創建對象觸發的,即:對象 = 類名() ;而對於 __call__ 方法的執行是由對象後加括號觸發的,即:對象() 或者 類()()
class Foo: def __init__(self): pass def __call__(self, *args, **kwargs): print(‘__call__‘) obj = Foo() # 執行 __init__ obj() # 執行 __call__View Code
.
Python之各種內置方法