第六章 與對(duì)象的深入交往

6.1 一切皆對(duì)象

6.2 屬性管理

6.3 我是風(fēng)兒,我是沙

6.4 內(nèi)存管理


6.1

.運(yùn)算符

涨缚。如果用dir(lisy)調(diào)查list的屬性,能看到一個(gè)屬性是_add_,從樣式上看,_add_是特殊方法策治,它特殊脓魏,在這個(gè)方法定義了"+"運(yùn)算符對(duì)于對(duì)象的意義兰吟,兩個(gè)list的對(duì)象相加時(shí)會(huì)進(jìn)行合并列表的操作。


print([1,2,3] + [5,6,9]) ? ? ?? #得到[1, 2, 3, 5, 6, 9]

print("abc" +"xyz") ? ? ? ? ? #連接字符串茂翔,獲得"abcxyz"

實(shí)際上執(zhí)行了如下的操作:

print("abc".__add__("xyz"))


運(yùn)算符混蔼,比如+,-珊燎,>惭嚣,<,and, or等都是通過特殊方法實(shí)現(xiàn)的悔政,比如:

__mul__ :*

__or__: or

??:列表在python中是不可以相減的晚吞,如下,則會(huì)顯示運(yùn)行錯(cuò)誤



我們可以創(chuàng)建一個(gè)列表的子類谋国,通過增加__sub__()方法槽地,來添加減法操作的定義


即使__sub__()方法已經(jīng)在父類中定義過,但在子類中重新定義后烹卒,子類中的方法會(huì)覆蓋父類中的同名方法闷盔。

.元素的引用

常用方式


實(shí)際上程序運(yùn)行:


此外,還有其他方法旅急,比如:

__setitem__(x, y) ? #把下標(biāo)為x的元素?fù)Q為y

__delitem__(x) ? ? ? #刪除下標(biāo)為x的元素

__delitem__("x") ?? #對(duì)于詞典來說逢勾,刪除鍵為“a”的元素

.內(nèi)置函數(shù)的實(shí)現(xiàn)

與運(yùn)算符類似,許多內(nèi)置函數(shù)也都是調(diào)用對(duì)象的特殊方法藐吮。比如:


其它常用方法:

__abs__() ? #返回?cái)?shù)字的絕對(duì)值

__int__() ?? #取整數(shù)部分溺拱,往小取整



6.2 屬性管理

.屬性覆蓋的背后

。__dict__屬性: 一個(gè)類或?qū)ο髶碛械膶傩詴?huì)記錄在__dict__中谣辞,并以詞典形式表示出來迫摔,鍵為屬性名,值為對(duì)應(yīng)的屬性泥从。python在尋找對(duì)象的屬性時(shí)句占,會(huì)按照繼承關(guān)系依次尋找

例子:

輸出結(jié)果:


輸出順序是按照一下與summer對(duì)象的親近關(guān)系排列的,第一部分為summer對(duì)象自身的屬性躯嫉,也就是age纱烘。第二部分chicken類的屬性,比如fly和__init__()方法祈餐。第三部分為Bird類的屬性胳岂,比如feather诊沪,負(fù)責(zé)。最后一部分屬于object類器净,有諸如粘勒,__doc__之類的屬性

可以使用內(nèi)置函數(shù)dir來查看對(duì)象summer對(duì)象的屬性


對(duì)象的屬性是分層管理的,summer能接觸到的所有屬性,分別存在summer,Chicken,Bird,object這四層,然后我們需要調(diào)用某個(gè)屬性的時(shí)候至扰,Python會(huì)一層層向下遍歷,直到找到那個(gè)屬性塌碌,由于對(duì)象不需要重復(fù)存儲(chǔ)其祖先類的屬性渊胸,所以分層管理的機(jī)制可以節(jié)省存儲(chǔ)空間旬盯。

某個(gè)屬性可能在不同層被重復(fù)定義台妆,Python在向下遍歷的過程中,會(huì)選取先遇到的那一個(gè)胖翰。這也是屬性覆蓋的原理接剩,如果從summer調(diào)用chirp()方法,那么使用的將是和對(duì)象summer關(guān)系更近的Chicken的版本,而不是Bird的版本萨咳。即子類的屬性比父類的同名屬性有優(yōu)先權(quán)懊缺,這是屬性覆蓋的關(guān)鍵。

如果進(jìn)行賦值培他,那么python就不會(huì)分層深入查找了鹃两。比如:


盡管autumn修改了feather的屬性值,但他并沒有影響到Bird的類屬性舀凛。

也可以不依賴?yán)^承關(guān)系俊扳,直接去操作某個(gè)祖先類的屬性,比如:


實(shí)際上猛遍,相當(dāng)于修改Bird的__dict__: Bird.__dict__["feather"] = 3,但是直接進(jìn)行如下修改是不行的




同一個(gè)對(duì)象的不同屬性之間可能存在依賴關(guān)系馋记,當(dāng)某個(gè)屬性的修改,使我們希望依賴于該屬性的其他屬性也同時(shí)變化懊烤。Python提供了多種即時(shí)生產(chǎn)屬性的方法梯醒,其中一種稱為特性(property),特性使用內(nèi)置函數(shù)property()來創(chuàng)建腌紧,最多可以加載四個(gè)參數(shù)茸习,前三個(gè)參數(shù)為函數(shù),分別用于設(shè)置壁肋,獲取号胚,修改和刪除特性時(shí),Python應(yīng)該執(zhí)行的操作墩划,最后一個(gè)參數(shù)為特性的文檔涕刚,可以為一個(gè)字符串,起的是說明的作用乙帮,例子如下:


.__getattr__()方法

用__getattr__(self, name)來查詢即時(shí)生成的屬性杜漠。當(dāng)我們調(diào)用對(duì)象的一個(gè)屬性時(shí),如果通過__dict__機(jī)制,無法找到該屬性驾茴。那么python就會(huì)調(diào)用對(duì)象的__getattr__()方法,來即時(shí)生成該屬性盼樟。此外,即時(shí)生成屬性還有其他的方法锈至,比如使用descriptor類晨缴。



.6.3 我是風(fēng)兒,我是沙

峡捡。動(dòng)態(tài)類型击碗,python的變量不需要聲明,在賦值時(shí)们拙,變量可以重新復(fù)制為其他任意值稍途,這就是動(dòng)態(tài)類型的體現(xiàn)。

通過內(nèi)置函數(shù)id()砚婆,我們能查看到引用指向的是哪個(gè)對(duì)象械拍,這個(gè)函數(shù)能返回對(duì)象的編號(hào),也就是f返回對(duì)象的內(nèi)存地址装盯。

一個(gè)類可以有多個(gè)相等的對(duì)象坷虑,比如兩個(gè)長(zhǎng)字符可以是不同的對(duì)象,但他們的值可以相等埂奈。我們可以用is運(yùn)算來判斷兩個(gè)引用是否指向同一個(gè)對(duì)象

改變一個(gè)引用迄损,并不會(huì)影響其他引用的指向,從效果上看挥转,就是各個(gè)引用各自獨(dú)立海蔽,互不影響。如:


(當(dāng)a指向?qū)ο?绑谣,b依然指向?qū)ο?)

但注意以下情況:


在操作列表時(shí)党窜,如果通過元素引用改變了某個(gè)元素,那么列表對(duì)象自身會(huì)發(fā)生改變借宵,列表這種自身能發(fā)生改變的對(duì)象稱為可變對(duì)象(Mutable Object)幌衣,我們之前見過的詞典也是可變對(duì)象。但整數(shù)壤玫,浮點(diǎn)數(shù)和字符串豁护,則不能改變對(duì)象本身,賦值最多只能改變引用的指向欲间,這種對(duì)象稱為不可變對(duì)象楚里。

。從動(dòng)態(tài)類型看函數(shù)的參數(shù)傳遞

函數(shù)參數(shù)的傳遞猎贴,本質(zhì)上傳遞的是引用班缎,比如:


如果a是不可變對(duì)象蝴光,那么引用a和x之間相互獨(dú)立,即對(duì)參數(shù)x的操作并不會(huì)影響到引用a达址。

但如果傳遞的是可變對(duì)象蔑祟,情況就發(fā)生了變化,如下:


(通過引用可變對(duì)象沉唠,會(huì)影響到其它引用)

.內(nèi)存管理

我們可以使用標(biāo)準(zhǔn)庫中sys包中的getrefcount()疆虚,來查看某個(gè)對(duì)象的引用計(jì)數(shù)。需要注意的是满葛,當(dāng)把某一引用傳遞給getrefcount()時(shí)径簿,參數(shù)實(shí)際上是創(chuàng)建了一個(gè)臨時(shí)的引用,因此纱扭,getrefcount()所得到的結(jié)果會(huì)比期望的多1牍帚。

兩個(gè)對(duì)象可能相互引用儡遮,構(gòu)成引用環(huán)(Reference Cycle)


即使是單個(gè)對(duì)象乳蛾,只需自己引用自己,也能構(gòu)成引用環(huán)鄙币。


某個(gè)對(duì)象的引用計(jì)數(shù)可能減少肃叶,比如使用del關(guān)鍵字刪除某個(gè)引用,如果某個(gè)引用指向?qū)ο骯十嘿,那么當(dāng)這個(gè)引用被重新定向到其他某個(gè)對(duì)象時(shí)因惭,對(duì)象a的計(jì)數(shù)將減少


。垃圾回收

當(dāng)Python的某個(gè)對(duì)象的引用計(jì)數(shù)降為0绩衷,即沒有任何引用指向該對(duì)象時(shí)蹦魔,該對(duì)象就要成為被回收的垃圾了。

當(dāng)Python運(yùn)行時(shí)咳燕,會(huì)記錄其中分配對(duì)象和取消分配對(duì)象的次數(shù)勿决。當(dāng)兩者的差值高于某個(gè)閾值時(shí),垃圾回收才會(huì)啟動(dòng)招盲,可以通過gc模塊的get_threshold()方法低缩,查看該閾值

import gc

print(gc.get_threshold()) ? ? ? ? ? ? #返回(700, 10, 10)

返回(700, 10曹货, 10)咆繁,后面的兩個(gè)10是與分代回收相關(guān)的閾值,700即垃圾回收啟動(dòng)的閾值可以通過gc中的set_threshold()方法重新設(shè)置顶籽。當(dāng)然也可以手動(dòng)啟動(dòng)垃圾回收,即使用gc.collect()玩般。python除了基礎(chǔ)回收方式外,Python同時(shí)還采用了分代回收的策略礼饱。所以策略的基本假設(shè)是存活時(shí)間越久坏为,對(duì)象越不可能在后面的程序中變成垃圾设拟,對(duì)這樣一些“長(zhǎng)壽”對(duì)象,我們相信它們還有用處久脯,所以減少在垃圾回收中掃描它們的頻率纳胧。

Python將所有的對(duì)象分為0,1,2三代,所有的新建對(duì)象都是0代對(duì)象帘撰。當(dāng)某一代對(duì)象經(jīng)過垃圾回收依然存活跑慕,那它就會(huì)歸入下一代對(duì)象,垃圾回收啟動(dòng)時(shí)一定會(huì)掃描所有的0代對(duì)象摧找,如果0代經(jīng)過一定次數(shù)的垃圾回收核行,就會(huì)啟動(dòng)對(duì)0代和1代的掃描清理,當(dāng)1代也經(jīng)歷了一定次數(shù)的垃圾回收后蹬耘,就會(huì)啟動(dòng)對(duì)0芝雪,1,2代的掃描综苔,也就是對(duì)所有對(duì)象進(jìn)行掃描惩系。返回的(700, 10如筛, 10) 也就是說堡牡,每10次0代垃圾回收會(huì)配合1次1代的垃圾回收,而每10次1代圾回收杨刨,才會(huì)有1次2代的垃圾回收晤柄。同樣可以通過gc中的set_threshold()方法來調(diào)整次數(shù),比如對(duì)2代對(duì)象進(jìn)行更頻繁的掃描妖胀,如:

import gc

gc.set_threshold(700,10,5) ? ? ? ? ? ? ? ? ? #調(diào)整次數(shù)芥颈,對(duì)2代對(duì)象進(jìn)行更頻繁的掃描

print(gc.get_threshold())

。孤立的引用環(huán)

引用環(huán)的存在給上面的垃圾回收機(jī)制帶來很大的困難赚抡,這些引用環(huán)可能構(gòu)成無法使用爬坑,但上面的計(jì)數(shù)不為0的一些對(duì)象:

a = []

b = [a]

a.append(b)

del a

del b

刪了a,b引用之后,這兩個(gè)對(duì)象不可能再?gòu)某绦蛑姓{(diào)用怕品,也就沒有什么用處妇垢,但是由于引用環(huán)的存在,兩個(gè)對(duì)象的引用計(jì)數(shù)都沒有降到零肉康,所以不會(huì)被垃圾回收闯估。

為了回收引用環(huán),Python會(huì)復(fù)制每個(gè)對(duì)象的引用計(jì)數(shù)吼和,可以記為gc_ref涨薪。假設(shè),每個(gè)對(duì)象i炫乓,該計(jì)數(shù)為gc_ref_i刚夺。Python會(huì)便利所有的對(duì)象i,對(duì)于每個(gè)對(duì)象i所引用的對(duì)象j献丑,將相應(yīng)的gc_ref_j減1,在結(jié)束遍歷后侠姑,gc_ref不為0的對(duì)象和這些對(duì)象引用的對(duì)象以及繼續(xù)更下游引用的對(duì)象创橄,需要被保留,而其他對(duì)象則被垃圾回收莽红。


代碼地址:https://gitee.com/mabingqi/learn_programming_from_python/tree/master/

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末妥畏,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子安吁,更是在濱河造成了極大的恐慌醉蚁,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,470評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鬼店,死亡現(xiàn)場(chǎng)離奇詭異网棍,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)妇智,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門滥玷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人俘陷,你說我怎么就攤上這事罗捎。” “怎么了拉盾?”我有些...
    開封第一講書人閱讀 162,577評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)豁状。 經(jīng)常有香客問我捉偏,道長(zhǎng),這世上最難降的妖魔是什么泻红? 我笑而不...
    開封第一講書人閱讀 58,176評(píng)論 1 292
  • 正文 為了忘掉前任夭禽,我火速辦了婚禮,結(jié)果婚禮上谊路,老公的妹妹穿的比我還像新娘讹躯。我一直安慰自己,他們只是感情好缠劝,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評(píng)論 6 388
  • 文/花漫 我一把揭開白布潮梯。 她就那樣靜靜地躺著,像睡著了一般惨恭。 火紅的嫁衣襯著肌膚如雪秉馏。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,155評(píng)論 1 299
  • 那天脱羡,我揣著相機(jī)與錄音萝究,去河邊找鬼免都。 笑死,一個(gè)胖子當(dāng)著我的面吹牛帆竹,可吹牛的內(nèi)容都是我干的绕娘。 我是一名探鬼主播,決...
    沈念sama閱讀 40,041評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼栽连,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼业舍!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起升酣,我...
    開封第一講書人閱讀 38,903評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤舷暮,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后噩茄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體下面,經(jīng)...
    沈念sama閱讀 45,319評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評(píng)論 2 332
  • 正文 我和宋清朗相戀三年绩聘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了沥割。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,703評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡凿菩,死狀恐怖机杜,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情衅谷,我是刑警寧澤椒拗,帶...
    沈念sama閱讀 35,417評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站获黔,受9級(jí)特大地震影響蚀苛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜玷氏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評(píng)論 3 325
  • 文/蒙蒙 一堵未、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧盏触,春花似錦渗蟹、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至诗宣,卻和暖如春膘怕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背召庞。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工岛心, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留来破,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,711評(píng)論 2 368
  • 正文 我出身青樓忘古,卻偏偏與公主長(zhǎng)得像徘禁,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子髓堪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • 6.1 一切皆對(duì)象 6.1.1 運(yùn)算符 兩個(gè)對(duì)象是否能進(jìn)行運(yùn)算送朱,首先就要看相應(yīng)的對(duì)象是否有特殊方法。若對(duì)象沒有此方...
    SibyLtuI閱讀 290評(píng)論 0 0
  • 6.1一切皆對(duì)象 6.2屬性管理 6.3我是風(fēng)兒干旁,我是沙 6.4內(nèi)存管理 6.11運(yùn)算符 兩個(gè)對(duì)象能否可以運(yùn)算驶沼,關(guān)...
    HXXHXX閱讀 228評(píng)論 0 0
  • 1.元類 1.1.1類也是對(duì)象 在大多數(shù)編程語言中,類就是一組用來描述如何生成一個(gè)對(duì)象的代碼段争群。在Python中這...
    TENG書閱讀 1,263評(píng)論 0 3
  • python內(nèi)存管理是通過引用計(jì)數(shù)來實(shí)現(xiàn)的回怜。當(dāng)對(duì)象的引用計(jì)數(shù)為0時(shí),會(huì)被gc回收换薄。 為了探索對(duì)象在內(nèi)存的存儲(chǔ)玉雾,我們...
    冬季戀歌1218閱讀 1,657評(píng)論 0 2
  • 本章前半部分,探索Python“一切皆對(duì)象”背后的含義轻要;后半部分深入到對(duì)象相關(guān)的重要機(jī)制复旬,如動(dòng)態(tài)類型和垃圾回收。 ...
    Guodw閱讀 196評(píng)論 0 0