日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

面向对象进阶(二)----------类的内置方法

發(fā)布時間:2023/12/6 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 面向对象进阶(二)----------类的内置方法 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、isinstance(obj,cls)和issubclass(sub,super)

1. isinstance(obj,cls): 檢查是否obj是否是類 cls 的對象

class Player:passp = Player()print(isinstance(p, Player))>>> Ture

?

2.?issubclass(sub, super): 檢查sub類是否是 super 類的派生類

class Player:passclass Basketball(Player):passprint(issubclass(Basketball, Player))>>> Ture

?

二、__getattribute__

1. 回顧__getattr__方法

class Player:x = 23y = 6def __init__(self):passdef __getattr__(self, item):print('不存在%s屬性' % item)p = Player() p.x p.xy>>> 不存在xy屬性

?

2. __getattribute__方法演示

class Player:x = 23y = 6def __init__(self):passdef __getattribute__(self, item):print('存不存在該屬性都會觸發(fā)__getattribute__方法')p = Player() p.x p.xy>>> 存不存在該屬性都會觸發(fā)__getattribute__方法

?

3. __getattr__與__getattribute__同時存在時

class Foo:def __init__(self, x):self.x = xdef __getattr__(self, item):print('執(zhí)行的是__getattr__')# return self.__dict__[item]def __getattribute__(self, item):print('不管是否存在,__getattribute都會執(zhí)行')raise AttributeError('拋出一個錯誤')f1=Foo(10) f1.x f1.xxxxxx>>> 不管是否存在,__getattribute都會執(zhí)行#當__getattribute__與__getattr__同時存在,只會執(zhí)行__getattrbute__, 若__getattribute__在執(zhí)行過程中拋出異常AttributeError, 則先執(zhí)行__getattribute__,然后執(zhí)行__getattr__

?

三、__setitem__, __getitem, __delitem__

1.?__setitem__, __getitem__, __delitem__都是 obj[‘屬性’]的方式去操作屬性時觸發(fā)的方法

?__getitem__:obj['屬性'] 時觸發(fā)
__setitem__:obj['屬性']=屬性的值 時觸發(fā)
__delitem__:del obj['屬性'] 時觸發(fā)

2.與__getattr__, __setattr__, __delattr__的同和異

同:賦值的底層原理都一樣

f1.name = 'lebron' #做的就是往屬性字典里添加或覆蓋值 原理:----->__setattr__----->f1.__dict__['name'] = 'lebron'f1['name'] = 'lebron' 原理:----->__setitem__----->f1.__dict__['name'] = 'lebron'#兩個方法的底層都是一樣的,只不過通過__setattr__,__setitem__中轉(zhuǎn)了一下

異:

__getattr__,__setattr__,__delattr__
obj點的方式去操作屬性時觸發(fā)的方法
__getitem__,__setitem_,__delitem__
obj[‘屬性’]的方式去操作屬性時觸發(fā)的方法


__getattr__:obj.屬性不存在時觸發(fā)
__setattr__:obj.屬性=屬性的值 時觸發(fā)
__delattr__:del obj.屬性 時觸發(fā)

__getitem__:obj['屬性'] 時觸發(fā)
__setitem__:obj['屬性']=屬性的值 時觸發(fā)
__delitem__:del obj['屬性'] 時觸發(fā)

class Foo:def __init__(self,name):self.name=namedef __getitem__(self, item):print(self.__dict__[item])def __setitem__(self, key, value):self.__dict__[key]=valuedef __delitem__(self, key):print('del obj[key]時,我執(zhí)行')self.__dict__.pop(key)def __delattr__(self, item):print('del obj.key時,我執(zhí)行')self.__dict__.pop(item)f1=Foo('sb') f1['age']=18 f1['age1']=19 del f1.age1 del f1['age'] f1['name']='alex' print(f1.__dict__)

>>>

? del obj.key時,我執(zhí)行
? del obj[key]時,我執(zhí)行
? {'name': 'alex'}

?

四、__str__, __repr__

__str__: 控制返回值,并且返回值必須是str類型,否則報錯

__repr__:控制返回值并且返回值必須是str類型,否則報錯

__repr__是__str__的替代品,如果__str__存在,直接按__str__的返回值,返回信息,不會執(zhí)行__repr__,如果不存在,會執(zhí)行__repr__,并得到__repr__的返回值

li = list('12345') print(type(li)) def foo():pass print(type(foo)) >>> <class 'list'> <class 'function'>#調(diào)用了類內(nèi)部的__str__方法,從而打印出<class 'list'>, <class 'function'> class Foo:def __init__(self, name, age):self.name = nameself.age = agedef __repr__(self):return '名字是%s,年齡是%s' %(self.name, self.age)def __str__(self):return 'name is %s, age is %s' %(self.name, self.age) p1 = Foo('chen', '23') print(p1)>>> name is chen, age is 23#__str__和__repr__都存在時,只會執(zhí)行__str__方法

?

五、自定制格式化字符串__format__

format_dic = {'ymd':'{0.year}{0.mon}{0.day}','y:m:d':'{0.year}:{0.mon}:{0.day}','y-m-d':'{0.year}-{0.mon}-{0.day}' } class Date:def __init__(self, year, mon, day):self.year = yearself.mon = monself.day = daydef __format__(self, format_spec):if not format_spec or format_spec not in format_dic: #用戶輸入的格式不存在時,使用默認的格式format_spec = 'y:m:d'return format_dic[format_spec].format(self) d = Date('2019','04','01') print(d.__format__('y-m-d')) print(d.__format__('y:m:d')) print(d.__format__('ymd')) print(d.__format__('asdf'))>>> 2019-04-01 2019:04:01 20190401 2019:04:01

?

六、__slots__

1.__slots__是什么:是一個類變量,變量值可以是列表,元祖,或者可迭代對象,也可以是一個字符串(意味著所有實例只有一個數(shù)據(jù)屬性)
2.引子:使用點來訪問屬性本質(zhì)就是在訪問類或者對象的__dict__屬性字典(類的字典是共享的,而每個實例的是獨立的)
3.為何使用__slots__: 字典會占用大量內(nèi)存,如果你有一個屬性很少的類,但是有很多實例,為了節(jié)省內(nèi)存可以使用__slots__取代實例的
__dict__
當你定義__slots__后,__slots__就會為實例使用一種更加緊湊的內(nèi)部表示。實例通過一個很小的固定大小的數(shù)組來構(gòu)建,而不是為每個實
例定義一個字典。
4.注意事項:__slots__的很多特性都依賴于普通的基于字典的實現(xiàn)。另外, 定義了__slots__后的類不再支持一些普通類特性了,比如多
繼承。大多數(shù)情況下,你應(yīng)該只在那些經(jīng)常別使用的用作數(shù)據(jù)結(jié)構(gòu)的類上定義
關(guān)于__slots__的一個常見誤區(qū)是它可以作為一個封裝工具來防止用戶給實例增加新的屬性。盡管使用__slots__可以達到這樣的目的,但是
這個并不是它的初衷。 更多的是用來作為一個內(nèi)存優(yōu)化工具。
class Foo:__slots__ = ['name', 'age'] #__dict__ = {'name': None, 'age': None} p = Foo() p.name = 'chen' p.age = '18' #print(p.__dict__) 報錯, __slots__方法下,實例化對象不存在屬性字典 #p.height = '1.8' 報錯,__slots__方法下,實例化對象只能設(shè)置指定的屬性

?

七、__doc__

類的描述信息

class Foo: '我是描述信息' pass print(Foo.__doc__)>>>'我是描述信息'

該屬性無法被繼承

class Foo:'我是描述信息'passclass Bar(Foo):pass print(Bar.__doc__) #該屬性無法繼承給子類>>> None

?

八、?__module__和__class__

 __module__ 表示當前操作的對象在那個模塊

 __class__ ? ? 表示當前操作的對象的類是什么

from test import Playerp = Player('lebron_james', 34, '2.03m')print(p.__module__) print(p.__class__)>>> test #輸出模塊名 <class 'test.Player'> #輸出對象的類名

?

九、__del__

析構(gòu)方法,當對象在內(nèi)存中被釋放時,自動觸發(fā)執(zhí)行。

注:如果產(chǎn)生的對象僅僅只是python程序級別的(用戶級),那么無需定義__del__, 如果產(chǎn)生的對象的同時還會向操作系統(tǒng)發(fā)起系統(tǒng)調(diào)用,即一個對象有用戶級與內(nèi)核級兩種資源,比如(打開一個文件,創(chuàng)建一個數(shù)據(jù)庫鏈接),則必須在清除對象的同時回收系統(tǒng)資源,這就用到了__del__

1. 簡單示范

class Foo:def __del__(self):print('執(zhí)行我啦')f1=Foo() del f1 print('------->')>>> 執(zhí)行我啦 #刪除f1對象,觸發(fā)__del__方法 ------->class Foo:def __del__(self):print('執(zhí)行我啦')f1=Foo() print('------->')>>> -------> 執(zhí)行我啦 #程序執(zhí)行完畢,釋放f1對象內(nèi)存,觸發(fā)__del__方法

?

2. 典型的應(yīng)用場景:

創(chuàng)建數(shù)據(jù)庫類,用該類實例化出數(shù)據(jù)庫鏈接對象,對象本身是存放于用戶空間內(nèi)存中,而鏈接則是由操作系統(tǒng)管理的,存放于內(nèi)核空間內(nèi)存中。

當程序結(jié)束時,python只會回收自己的內(nèi)存空間,即用戶態(tài)內(nèi)存,而操作系統(tǒng)的資源則沒有被回收,這就需要我們定制__del__,在對象被刪除前向操作系統(tǒng)發(fā)起關(guān)閉數(shù)據(jù)庫鏈接的系統(tǒng)調(diào)用,回收資源

這與文件處理是一個道理:

f=open('a.txt') #做了兩件事,在用戶空間拿到一個f變量,在操作系統(tǒng)內(nèi)核空間打開一個文件 del f #只回收用戶空間的f,操作系統(tǒng)的文件還處于打開狀態(tài)#所以我們應(yīng)該在del f之前保證f.close()執(zhí)行,即便是沒有del,程序執(zhí)行完畢也會自動del清理資源,于是文件操作的正確用法應(yīng)該是 f=open('a.txt') 讀寫... f.close() 很多情況下大家都容易忽略f.close,這就用到了with上下文管理

?

十、__enter__和__exit__

我們知道在操作文件對象的時候可以這么寫

with open('a.txt') as f:'代碼塊'

上述叫做上下文管理協(xié)議,即with語句,為了讓一個對象兼容with語句,必須在這個對象的類中聲明__enter__和__exit__方法。

?

1.上下文管理協(xié)議

class Open:def __init__(self, name):self.name = namedef __enter__(self):print('出現(xiàn)with語句,對象的__enter__被觸發(fā),有返回值則賦值給as聲明的變量')return selfdef __exit__(self, exc_type, exc_val, exc_tb):print('with中代碼塊執(zhí)行完畢時執(zhí)行__exit__')with Open('a.txt') as f:print('=====>執(zhí)行代碼塊')print(f,f.name)>>> 出現(xiàn)with語句,對象的__enter__被觸發(fā),有返回值則賦值給as聲明的變量 =====>執(zhí)行代碼塊 <__main__.Open object at 0x0000013191B98710> a.txt with中代碼塊執(zhí)行完畢時執(zhí)行__exit__

?

2. __exit__()中的三個參數(shù)分別代表 異常類型,異常值 和 追溯信息,with語句中代碼塊出現(xiàn)異常,則with后的代碼都無法執(zhí)行。

class Open:def __init__(self, name):self.name = namedef __enter__(self):print('出現(xiàn)with語句,對象的__enter__被觸發(fā),有返回值則賦值給as聲明的變量')def __exit__(self, exc_type, exc_val, exc_tb):print('with中代碼塊執(zhí)行完畢時執(zhí)行__exit__')print(exc_type)print(exc_val)print(exc_tb)with Open('a.txt') as f:print('=====>執(zhí)行代碼塊')raise AttributeError('***著火啦,救火啊***') print('0'*100) # ------------------------------->不會執(zhí)行

?

3. 如果__exit()返回值為True,那么異常會被清空,就好像啥都沒發(fā)生一樣,with中的代碼將不會繼續(xù)執(zhí)行,而with后的語句正常執(zhí)行。

class Open:def __init__(self, name):self.name = namedef __enter__(self):print('出現(xiàn)with語句,對象的__enter__被觸發(fā),有返回值則賦值給as聲明的變量')def __exit__(self, exc_type, exc_val, exc_tb):print('with中代碼塊執(zhí)行完畢時__exit__')print(exc_type)print(exc_val)print(exc_tb)return Truewith Open('a.txt') as f:print('=====>執(zhí)行代碼塊')raise AttributeError('***著火啦,救火啊***') print('0'*100) #------------------------------->會執(zhí)行

?

4.模擬open

class Open():def __init__(self, filename, mode='r', encoding='utf-8'):self.file = open(filename, mode, encoding=encoding)def __enter__(self):return self.filedef __exit__(self, exc_type, exc_val, exc_tb):self.file.close()return Truedef __getattr__(self, item):return getattr(self.file, item)with Open('a.txt','w') as f:print(f)f.write('aaaaaa')f.wasdf #拋出異常,交給__exit__處理

5. 總結(jié):

with obj as f:'代碼塊'1. with obj -----> 觸發(fā)obj.__enter__(), 拿到返回值2. as f -----> f = 返回值3.with obj as f 等同于 f = obj.__enter__()4. 執(zhí)行代碼塊 一:沒有異常的情況下,整個代碼塊運行完畢后去觸發(fā)__exit__(),它的三個參數(shù)都為空 二:有異常的情況下,從異常出先的位置直接觸發(fā)__exit__a:如果__exit__()返回值為Ture,代表吞掉了異常,with中的代碼終止運行, with后的代碼正常運行b:如果__exit__()的返回值不為Ture,代表吐出了異常c:__exit__的運行完畢就代表了整個with語句的執(zhí)行完畢

?

6.?用途或者說好處:

1.使用with語句的目的就是把代碼塊放入with中執(zhí)行,with結(jié)束后,自動完成清理工作,無須手動干預(yù)。

2.在需要管理一些資源比如文件,網(wǎng)絡(luò)連接和鎖的編程環(huán)境中,可以在__exit__中定制自動釋放資源的機制,你無須再去關(guān)系這個問題,這將大有用處。

?

十一、__call__

對象后面加括號,觸發(fā)執(zhí)行。

注:構(gòu)造方法的執(zhí)行是由創(chuàng)建對象觸發(fā)的,即:對象 = 類名() ;

而對于 __call__ 方法的執(zhí)行是由對象后加括號觸發(fā)的,即:對象() 或者 類()

class Foo:def __init__(self):passdef __call__(self, *args, **kwargs):print('__call__')obj = Foo() # 執(zhí)行 __init__ obj() # 執(zhí)行 __call__

?

十二、__next__和__iter__實現(xiàn)迭代器協(xié)議

1. 簡單示范

class Foo:def __init__(self, x):self.x = xdef __iter__(self):return selfdef __next__(self):self.x += 1if self.x > 6:raise StopIterationreturn self.xf = Foo(3)for i in f:print(i)

?

2.?練習(xí):簡單模擬range,加上步長

class Range:def __init__(self, start, end, step):self.start = startself.end = endself.step = stepdef __iter__(self):return selfdef __next__(self):self.start += self.stepif self.start > self.end:raise StopIterationreturn self.startr = Range(1,10,2)for i in r:print(i)>>> 3 5 7 9

?

3. 實現(xiàn)斐波那契數(shù)列

class Fib:def __init__(self):self.a = 1self.b = 1def __iter__(self):return selfdef __next__(self):self.a, self.b = self.b, self.a + self.bif self.a > 15:raise StopIterationreturn self.af = Fib()for i in f:print(i)

?

轉(zhuǎn)載于:https://www.cnblogs.com/cjsword/p/10642041.html

總結(jié)

以上是生活随笔為你收集整理的面向对象进阶(二)----------类的内置方法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。