面向對象進階(二)----------類的內置方法

一、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('存不存在該屬性都會觸發__getattribute__方法')p = Player()
p.x
p.xy>>>
存不存在該屬性都會觸發__getattribute__方法

?

3. __getattr__與__getattribute__同時存在時

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

?

三、__setitem__, __getitem, __delitem__

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

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

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

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

f1.name = 'lebron'   #做的就是往屬性字典里添加或覆蓋值

原理:----->__setattr__----->f1.__dict__['name'] = 'lebron'f1['name'] = 'lebron'  原理:----->__setitem__----->f1.__dict__['name'] = 'lebron'#兩個方法的底層都是一樣的,只不過通過__setattr__,__setitem__中轉了一下

異:

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


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

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

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]時,我執行')self.__dict__.pop(key)def __delattr__(self, item):print('del obj.key時,我執行')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時,我執行
? del obj[key]時,我執行
? {'name': 'alex'}

?

四、__str__, __repr__

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

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

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

li = list('12345')
print(type(li))  def foo():pass
print(type(foo))  >>>
<class 'list'>
<class 'function'>#調用了類內部的__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__都存在時,只會執行__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__是什么:是一個類變量,變量值可以是列表,元祖,或者可迭代對象,也可以是一個字符串(意味著所有實例只有一個數據屬性)
2.引子:使用點來訪問屬性本質就是在訪問類或者對象的__dict__屬性字典(類的字典是共享的,而每個實例的是獨立的)
3.為何使用__slots__: 字典會占用大量內存,如果你有一個屬性很少的類,但是有很多實例,為了節省內存可以使用__slots__取代實例的
__dict__
當你定義__slots__后,__slots__就會為實例使用一種更加緊湊的內部表示。實例通過一個很小的固定大小的數組來構建,而不是為每個實
例定義一個字典。
4.注意事項:__slots__的很多特性都依賴于普通的基于字典的實現。另外, 定義了__slots__后的類不再支持一些普通類特性了,比如多
繼承。大多數情況下,你應該只在那些經常別使用的用作數據結構的類上定義
關于__slots__的一個常見誤區是它可以作為一個封裝工具來防止用戶給實例增加新的屬性。盡管使用__slots__可以達到這樣的目的,但是
這個并不是它的初衷。 更多的是用來作為一個內存優化工具。
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__方法下,實例化對象只能設置指定的屬性

?

七、__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__

析構方法,當對象在內存中被釋放時,自動觸發執行。

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

1. 簡單示范

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

?

2. 典型的應用場景:

創建數據庫類,用該類實例化出數據庫鏈接對象,對象本身是存放于用戶空間內存中,而鏈接則是由操作系統管理的,存放于內核空間內存中。

當程序結束時,python只會回收自己的內存空間,即用戶態內存,而操作系統的資源則沒有被回收,這就需要我們定制__del__,在對象被刪除前向操作系統發起關閉數據庫鏈接的系統調用,回收資源

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

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

?

十、__enter__和__exit__

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

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

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

?

1.上下文管理協議

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

?

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

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

?

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

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

?

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. 總結:

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

?

6.?用途或者說好處:

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

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

?

十一、__call__

對象后面加括號,觸發執行。

注:構造方法的執行是由創建對象觸發的,即:對象 = 類名() ;

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

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

?

十二、__next__和__iter__實現迭代器協議

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.?練習:簡單模擬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. 實現斐波那契數列

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)

?

轉載于:https://www.cnblogs.com/cjsword/p/10642041.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/279773.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/279773.shtml
英文地址,請注明出處:http://en.pswp.cn/news/279773.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

BZOJ.3265.志愿者招募加強版(費用流SPFA)

題目鏈接 見上題。 每類志愿者可能是若干段&#xff0c;不滿足那個...全幺模矩陣(全單位模矩陣)的條件&#xff0c;所以線性規劃可能存在非整數解。 于是就可以用費用流水過去順便拿個rank2 233. //20704kb 300ms #include <queue> #include <cstdio> #include &…

谷歌相冊_Google相冊中的新存檔功能是什么?

谷歌相冊If you’re a Google Photos user, you’ve may have seen a new feature called “Archive” show up in the app’s sidebar. if not, don’t stress—it’s just now rolling out and not everyone has it yet. Since it’s new, here’s a quick look at what it i…

CenterOS 7安裝Nginx

1.wget http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm下載對應當前系統版本的nginx包(package) 2.rpm -ivh nginx-release-centos-7-0.el7.ngx.noarch.rpm建立nginx的yum倉庫 3.yum install nginx 下載并安裝nginx systemctl s…

Java的組合排列問題

從4個人中選2個人參加活動&#xff0c;一共有6種選法。 從n個人中選m個人參加活動&#xff0c;一共有多少種選法&#xff1f;C(m/n)C((m-1)/(n-1))C(m/(n-1))數學算法 public class Main {public static void main(String[] args) {System.out.println("請輸入總人數:&quo…

阿里云一鍵建站產品,阿里云自營建站-中小企業建站首選

阿里云推出的自營建站服務&#xff0c;這對于中小企業來說簡直是福利了&#xff0c;現在一般的公司都開始有了自己的官網&#xff0c;有可能就是因為你的官網設計的標準&#xff0c;大氣&#xff0c;客戶就會對你的信任度增加&#xff0c;從而促進一筆不小的訂單&#xff0c;這…

航拍拉近拉遠鏡頭_什么是遠攝鏡頭?

航拍拉近拉遠鏡頭Telephoto lenses can be incredibly useful, but how is it different from other lenses, and when should you use it? 遠攝鏡頭可能非常有用&#xff0c;但是它與其他鏡頭有什么不同&#xff1f;何時使用&#xff1f; 什么是遠攝鏡頭&#xff1f; (What I…

數據庫的簡單了解

數據庫一、什么是數據庫存儲數據的倉庫將數據有組織&#xff0c;按照特定的格式存儲在介質上叫做數據庫二、比較多個數據庫系統a) Oracle 最好的數據庫沒有之一b) SQL server 最好的數據庫(windows)c) MySQL 甲骨文(Oracle) sun 開源三、SQL語言a) SQL(結構化查詢語句) …

阿里云對象存儲OSS支持版本管理特性

2019獨角獸企業重金招聘Python工程師標準>>> 阿里云對象存儲OSS現已經全面支持“對象版本管理”特性。該功能適用于所有的存儲類型以及區域。當Bucket啟用該特性后&#xff0c;“對象版本管理”功能可以保護和恢復誤刪除、誤覆蓋的數據。 對象存儲OSS“版本管理”具…

Python第一天學習---基礎語法

1.字符串的用法(String) Python 中的字符串有兩種索引方式&#xff0c;從左往右以 0 開始&#xff0c;從右往左以 -1 開始。Python中的字符串不能改變。Python 沒有單獨的字符類型&#xff0c;一個字符就是長度為 1 的字符串這三點是我覺得Python字符處理特別的一點 我們來看第…

教你幾招識別和防御Web網頁木馬

本文同時發表在&#xff1a;[url]http://netsecurity.51cto.com/art/200709/56360.htm[/url] 根據反病毒廠商Sophos今年的第一、第二季度報告&#xff0c;網頁已經超過電子郵件成為惡意軟件傳播時最喜歡使用的途徑&#xff0c;通過網頁傳播的惡意軟件平均每月增加300多種。而對…

apple tv設置_如何設置Apple TV播放個人iTunes庫

apple tv設置If you already have a lot of music and home videos in your iTunes library, you can easily stream it all to your Apple TV, and thus whatever output sources to which it is connected. 如果iTunes庫中已經有很多音樂和家庭視頻&#xff0c;則可以輕松地將…

[bzoj1050 HAOI2006] 旅行comf (kruskal)

傳送門 Description 給你一個無向圖&#xff0c;N(N<500)個頂點, M(M<5000)條邊&#xff0c;每條邊有一個權值Vi(Vi<30000)。給你兩個頂點S和T&#xff0c;求 一條路徑&#xff0c;使得路徑上最大邊和最小邊的比值最小。如果S和T之間沒有路徑&#xff0c;輸出”IMPOSS…

好程序員技術文檔HTML5開發中的javascript閉包

好程序員技術文檔HTML5開發中的javascript閉包&#xff0c;事實上&#xff0c;通過使用閉包&#xff0c;我們可以做很多事情。比如模擬面向對象的代碼風格;更優雅&#xff0c;更簡潔的表達出代碼;在某些方面提升代碼的執行效率&#xff0c;同時避免對命名空間的污染&#xff0c…

亞馬遜echo中國使用_如何使用亞馬遜的主要照片備份所有照片

亞馬遜echo中國使用Millions of people are Amazon Prime subscribers, but many of them don’t realize that in addition to free shipping and Prime Instant Video, they also get unlimited photo storage for all their computers and mobile devices. 數以百萬計的人是…

抽象SQL查詢:SQL-MAP技術的使用

什么是參數化查詢&#xff1f;我們來看百度百科對此的定義和示例&#xff1a; 一&#xff0c;定義 ------------------------------------------------------------------ 參數化查詢&#xff08;Parameterized Query 或 Parameterized Statement&#xff09;是指在設計與數據庫…

EF ORM

//新增UserInfo userInfo new UserInfo();userInfo.UserName "YANG";userInfo.UserPass "123";userInfo.Email "253qq.com";userInfo.RegTime System.DateTime.Now;Model1Container db new Model1Container();db.UserInfoSet.Add(userInfo…

如何使用echo.js實現圖片的懶加載(整理)

如何使用echo.js實現圖片的懶加載&#xff08;整理&#xff09; 一、總結 一句話總結&#xff1a;a、在img標簽中添加data-echo屬性加載真實圖片&#xff1a;<img class"loading" src"blank.gif" data-echo"圖片真實路徑" />&#xff0c;在…

還原出廠設置 擦除frp_如何備份,擦除和還原Apple Watch

還原出廠設置 擦除frpThe Apple Watch is, in its own right, a little tiny computer with data backup and security needs. Read on as we show you how to ensure your Apple Watch is backed up, wiped, and restored just like you’d do with your smartphone. Apple Wa…

exchange 2010 search mailbox 的幕后強大功能

鈴……….半夜中被一陣急促的手機鈴聲吵醒&#xff0c;年度服務客戶打來電話需要進行郵件的排查和刪除工作。問其原因&#xff0c;原來是組織中有人發了一封關于領導的不健康的郵件&#xff0c;并在企業內部進行了轉發&#xff0c;領導要求立即找出此類郵件并進行刪除。管理員深…

Apache HBase的現狀和發展

一、&#xff28;Base是什么 HBase(Hadoop Database)&#xff0c;是一個基于Google BigTable論文設計的高可靠性、高性能、可伸縮的分布式存儲系統。 它有以下特征&#xff1a; 1.HBase仍然是采用行存儲的&#xff0c;采用松散表的結構來獲得動態列的功能&#xff1b; 2.原生海…