第十四章 對(duì)象
在Python中,對(duì)象(object)是什么?我們先看前兩個(gè)概念:
(1)列表——收集變量(也就是數(shù)據(jù))
(2)函數(shù)——收集功能(也就是代碼)
而我們今天學(xué)的對(duì)象,則將是將這種收集思想再進(jìn)一步——收集列表和函數(shù)本身。
等等,收集了又怎樣?我們可以不用了解那么深入,只需要知道Python是面向?qū)ο螅╫bject oriented)的編程語言,有很多對(duì)象可以幫我們實(shí)現(xiàn)很多功能,我們不用自己寫出來,只要寫個(gè)代碼調(diào)用它就好了。
14.1 真實(shí)世界中的對(duì)象
在真實(shí)世界中,對(duì)象相當(dāng)于一個(gè)東西,它有自己的屬性(attribute)或特性(property),如大小、顏色等;也有動(dòng)作,如撿球、拋球等。
14.2 Python中的對(duì)象
在Python中,一個(gè)對(duì)象的特征就是屬性;動(dòng)作則稱為方法(method)。
如果在Python中定義一個(gè)“球”,我們可以給他建立如下定義:

什么是屬性?
屬性就是一些信息(數(shù)字、字符串等),其實(shí)也是變量的一種,只不過它包含在對(duì)象中。屬性可以:
(1)顯示:print ball.size
(2)賦值給自己:ball.color = 'green'
(3)賦值給其他變量:myColor = ball.color
(4)賦值給其他對(duì)象的屬性:myBall.color = yourBall.color
什么是方法?
方法其實(shí)就是包含在對(duì)象中的函數(shù)。
14.3 對(duì)象=屬性+方法
利用對(duì)象,可以將一個(gè)東西的屬性和方法(也就是你知道的事情和希望可以做的事情)收集到一起。屬性是信息,方法是動(dòng)作。
14.4 這個(gè)點(diǎn)是什么
前面我們看到:
(1)object.attribute
(2)object.method()
這兩種用法。中間的點(diǎn),是Python使用對(duì)象屬性和方法的一種記法,稱為“點(diǎn)記法”。
14.5 創(chuàng)建對(duì)象
Python創(chuàng)建對(duì)象一共有兩步:
(1)第一步是創(chuàng)建對(duì)象類(class),用來放入對(duì)象的描述或藍(lán)圖。
(2)第二部是創(chuàng)建對(duì)象的實(shí)例(instance)。
具體請(qǐng)看下面的例子:



初始化對(duì)象:__int__()方法
有時(shí)候,除了創(chuàng)建類和實(shí)例本身,我們還需要第三步——初始化(initializing)。
初始化可以使用一個(gè)特定的方法實(shí)現(xiàn):

假如現(xiàn)在print myBall,得到的會(huì)是這樣的結(jié)果:

要改變這個(gè)信息,需要用到一個(gè)__str__()方法,它是一個(gè)“類方法”:
改變類型:__str__()方法
就像init方法一樣,str方法是Python創(chuàng)建類時(shí)自動(dòng)包含的“魔法方法”,也叫特殊方法(special method)。
__str__()方法在這里的含義是,告訴Python打印一個(gè)對(duì)象時(shí),具體要顯示什么內(nèi)容,默認(rèn)會(huì)顯示下面的內(nèi)容:
(1)實(shí)例在哪里定義(默認(rèn)為__main__)
(2)類名(Ball)
(3)存儲(chǔ)實(shí)例的具體空間(這里是0x109577dd0)
下面的例子使用了__str__()改變了打印的對(duì)象:

什么是self
我們前面多次用到了“self”,如下面這個(gè)例子:
def bounce(self):
這個(gè)self是什么意思呢?我們先看Ball類創(chuàng)造的兩個(gè)實(shí)例:
catersBall = Ball("red", "small", "down")
warrensBall = Ball("green", "medium", "up")
這樣,我們調(diào)用其中一個(gè)實(shí)例時(shí)(以warrens為例),可以直接用warrensBall.bounce來實(shí)現(xiàn):
(1)首先,bounce是一個(gè)方法;
(2)方法必須知道是哪個(gè)實(shí)例調(diào)用了它:是caters,還是warrens或其他?
(3)因此,前面的def bounce(self)方法中的self參數(shù),就會(huì)告訴bounce方法,是warrens調(diào)用了這個(gè)方法。以上成為實(shí)例引用(instance reference)。
附:我花了好長時(shí)間也沒弄明白這個(gè)self方法,另外這一章也感覺比之前難懂很多,那么就先放放,等上手了例題再回來補(bǔ)充吧~
14.6 一個(gè)示例類——HotDog
之前我們做過了熱狗的排列組合練習(xí),現(xiàn)在我們來給熱狗們?cè)O(shè)置一些屬性和方法,讓這個(gè)程序更加智能些。
首先給熱狗設(shè)置一些屬性:
(1)cooked_level:代表熱狗的生熟程度,0~3為生,5表示烤好,8以上已經(jīng)烤焦了!
(2)cooked_string:描述熱狗生熟程度的字符串。
(3)condiments:熱狗上的配料列表,如番茄醬、芥末醬等。
然后是熱狗的一些方法:
(1)cook():烤熱狗。
(2)add_condiment():給熱狗加上配料。
(3)__init__():創(chuàng)建實(shí)例并設(shè)置默認(rèn)屬性。
(4)__str__():讓print的結(jié)果好看點(diǎn)。
下面是步驟:
(1)首先需要定義熱狗這個(gè)類:使用__init__方法

(2)建立一個(gè)烤熱狗的方法:cook(),其中的time是用來增加烤制級(jí)別的。

(3)創(chuàng)建熱狗的一個(gè)實(shí)例,并檢查它的屬性。

(4)把以上內(nèi)容都放到一個(gè)程序中,并運(yùn)行:

(5)現(xiàn)在來測試cook方法:

(6)增加其他的功能:顯示、加配料等




14.7 隱藏?cái)?shù)據(jù)
如果限制對(duì)對(duì)象的數(shù)據(jù)訪問,使得它只能通過方法來獲取數(shù)據(jù)、修改數(shù)據(jù),這就叫做數(shù)據(jù)隱藏(data hiding)。
14.8 多態(tài)和繼承
接下來我們學(xué)習(xí)對(duì)象最重要的兩個(gè)方面:多態(tài)(polymorphism)和繼承(inheritance)。這兩個(gè)詞有點(diǎn)深?yuàn)W,但正因?yàn)橛羞@兩方面,才讓對(duì)象如此有用。
(1)多態(tài)——同一個(gè)方法,不同的行為
多態(tài)簡單來說就是:同名的方法,在不同的類中,可以實(shí)現(xiàn)不同的行為。
例如,假設(shè)我們要建立一個(gè)程序做幾何題,分別計(jì)算不同形狀(如正方形和三角形)的面積,這時(shí)候我們可以建立兩個(gè)類,然后按下面的來操作:


以上兩個(gè)形狀,都用了getArea的方法,但每個(gè)形狀的方法做的工作不同,這就是多態(tài)的一個(gè)例子。
(2)繼承——向父母學(xué)習(xí)
在真實(shí)的(非編程的)世界中,人們可以從他們的父母或其他家人處繼承一些東西,如財(cái)物、身體特征等。而在面向?qū)ο缶幊讨?,類可以從其他類那里繼承屬性和方法,這樣的類稱為一個(gè)“家族”,“家族”中的每個(gè)類共享相同的屬性和方法。這樣一來,給“家族”新增成員的時(shí)候,新的類就不用從頭開始寫起。
從其他類繼承屬性或方法的類,我們成為派生類(derived class)或子類(subclass)。我們看一下下面的例子:
假如我們要建立一個(gè)游戲,玩家一路上可以撿起不同的東西,如食物、錢或衣服。我們建立一個(gè)類,叫GameObject。它有一些屬性如name、coin、apple和hat等;它還有些方法,如pickUp()等。所有的游戲?qū)ο蠖加泄餐姆椒ê蛯傩浴?/p>
另外我們還有Coin這個(gè)子類,從GameObject派生。它需要繼承GameObject的name屬性和pickUp等方法,并需要一個(gè)value屬性和一個(gè)spend()方法。
下面是這些類的代碼:

14.9 未雨綢繆
上面的代碼看似沒有什么實(shí)質(zhì)內(nèi)容,但它有助于我們提前思考、組織想法,并給其他人解釋我們要做什么。這種“未雨綢繆”的方法,我們也可以“空函數(shù)”或代碼樁(code stub)實(shí)現(xiàn)。
要建立代碼樁,可以使用pass關(guān)鍵字作為占位符,如:

你學(xué)到了什么
(1)什么是對(duì)象、屬性和方法
(2)什么是類,以及如何創(chuàng)建類的實(shí)例
(3)特殊方法:__init__()和__str__()
(4)多態(tài)、繼承和代碼樁
練習(xí)題
記在前面,先區(qū)分一下類、對(duì)象和實(shí)例,感覺現(xiàn)在還沒弄明白。書上說的是,“類”只是對(duì)象的定義或藍(lán)圖,從這個(gè)藍(lán)圖建立對(duì)象時(shí)得到的就是實(shí)例。這里放一個(gè)討論的連接,下面是另一種比喻,日后繼續(xù)加深印象~

(1)為BankAccount建立一個(gè)類定義。它的屬性包括賬戶名(字符串)、賬號(hào)(字符串或整數(shù))和余額(浮點(diǎn)數(shù)),另外還需要有一些方法用來顯示余額、存錢和取錢。


(2)建立一個(gè)可以掙利息的類,叫InterestAccount。它繼承BankAccount的屬性和方法,并且有一個(gè)對(duì)應(yīng)的利息率的屬性,另外還要有一個(gè)方法計(jì)算及更新余額(年利息)。
先回顧一下子類的建立方法:
class 子類名(父類名):



小結(jié)
這一章學(xué)的挺不痛快,原因一是沒之前那么簡單,涉及到類、對(duì)象和實(shí)例的關(guān)系比較抽象,不能一下子明白;第二是不太自信,碰到比較難、比較陌生的題,會(huì)畏懼、會(huì)害怕。
這一章也是目前我參考網(wǎng)上其他學(xué)習(xí)筆記最多的一章,總的來說付出跟收獲是成比例的,繼續(xù)加油吧~