Python之父教你如何搞倒對象
The best way to learn a programming language is to write a lot of code and read a lot of code.
GIF
不好意思,今天要找的對象不是真實世界中的對象。
在真實的世界裡,平時A和B聊天:
在Python中定義什麼是對象也可以作為一個很好的起點。拿球來舉個例子。可以操作一個球,比如撿球、拋球、踢球或者充氣等。我們把這些操作稱為動作(action)。還可以通過指出球的顏色、大小和重量來描述一個球。這些就是球的屬性(attribute)。
可以通過描述特徵或屬性來描述一個對象。球的屬性之一是它的形狀。大多數球都是圓形。還有一些其他的屬性,比如顏色、大小、重量和價格。屬性的另一個說法是特性。
真實世界的真實對象(物體)包括兩個方面。
在Python中,也是如此。一個對象的特徵(或「你知道的事情」)也稱為屬性(attribute),這應該很好理解。動作(或「能夠對對象做的操作」)稱為方法(method)。
如上圖聊天中,關於球的屬性在Python中可能描述為:
對於球做的操作可能包括:
什麼是屬性
屬性就是你所知道(或者可以得出)的關於球的所有方面。球的屬性就是一些信息(數字、字元串等等)。聽起來熟悉吧,其實,它們就是變數,只不過是包含在對象中的變數。
可以顯示:
print ball.size
可以為它們賦值:
ball.color="green"
可以把它們賦給常規的、不是對象的變數:
myColor=ball.color
還可以把它們賦給其他對象的屬性:
myBall.color=yourBall.color
什麼是方法
方法就是可以對對象做的操作,它們是一些代碼塊,可以調用這些代碼塊來完成某個工作。這聽起來更熟悉吧,方法就是包含在對象中的函數(也就是上一篇中我們討論的內容積木)。
函數能做的,方法都可以做到,包括傳遞參數和返回值。
所以利用對象,可以把一個東西的屬性和方法(你知道的事情和你可以做的事情)收集在一起。屬性是信息,方法是動作。
這個點是什麼
在前面的例子中,你可能已經注意到對象名與屬性或方法名之間的點。這是Python使用對象屬性和方法的一種記法:
object.attribute
或
object.method()
這稱為點記法,很多編程語言中都使用了這種記法。
創建對象
Python中創建對象包括兩步。
下面來看一個建立類和實例的例子。
類定義
我們先創建一個簡單的Ball類:
以上代碼是一個球的類定義,其中只有一個方法bounce()。
不過,屬性呢?嗯,屬性並不屬於類,它們屬於各個實例。因為每個實例可以有不同的屬性。
對象實例
前面提到過,類定義並不是一個對象,它只是創建對象的第一步,這只是藍圖。現在我們來進行第二步,建立一個實例,用藍圖來蓋真正的房子。
如果想創建Ball的一個實例,可以這樣做
這個球還沒有任何屬性,所以下面給它提供一些屬性:
這是對象定義屬性的一種方法,另一種方法叫初始化對象,後面會討論到。
到這裡,我們已經創建了一個對象Ball了。接下來我們來試試它的方法。我們要這樣使用bounce()方法:
我們把上述這些創建Ball對象和使用bounce()方法的代碼都放在一個程序里,增加一些print語句來看發生了什麼。程序如下:
運行這個程序,可以看到下面的結果:
可以看出,調用bounce()方法會把球的方向(direction)從下(down)改為上(up),這正是bounce()方法中的代碼所要做的。
初始化對像(__init__()方法)
我們剛剛說了,對象定義屬性的方法有兩種,上述Ball對象在創建之後,才對myBall的屬性size、color和direction中填入內容。就像剛才的那樣:
如果我們想把對象的屬性在開始時就設置成一種我們希望的描述(狀態或條件)以備使用,我們可以使用初始化對象的方法。
創建類定義時,可以定義一個特定的方法,名為__init__(),注意在init前後是兩條下劃線(_)。我們只要創建這個類的一個新實例,就會運行這個方法。
當然,你可以向__init__()方法傳遞參數,這樣創建實例時就會把屬性設置為你希望的值。我們看下面的例子:
運行這個程序:
得出的結果與第一個對象屬性定義方法是相同的。區別在於,本例使用了__init__()方法來設置屬性。
__init__()方法會在對象創建時完成初始化。每個對象都內置有一個__init__()方法。如果你在類定義中沒有加入自己的__init__()方法,就會有這樣一個內置方法接管,它的工作就是創建對象。
__str__()方法
另一個特殊方法是__str__(),它會告訴Python列印(print)一個對象時具體顯示什麼內容。Python會默認以下內容。
如果我們在上述的例子的IDLE結果中,再輸入以下代碼,結果如下:
因為在創建對象時,我們沒有定義自己的__str__()方法。所以這時Python會默認告訴我們剛建立的實例myBall是在__main__(這是程序的主部分)中定義的,類名是Ball,而存儲實例的內存位置是0x0000000003331B88。
不過,如果你希望列印一個對象時能顯示其他的內容,我們可以定義自己的__str__()方法,這會覆蓋內置的__str__()方法。如下例子:
運行這個程序,可以得到下面的結果:
這樣看起來是不是比好多了。
什麼是self
你可能已經注意到,在類屬性和方法定義中多處出現了「self」,比如:
self是什麼意思?
我們說過,可以使用藍圖蓋很多個房子,那麼,使用一個類也就可以創建多個對象實例,例如:
調用其中一個實例的方法時,像這樣:
方法必須知道是哪個實例調用了它,是myBall需要反彈?還是yourBall?self參數會告訴方法哪個對象調用它。這稱為實例引用。
不過,調用方法時,myBall.bounce()的括弧里沒有參數,但是方法里卻有一個self參數。既然我們並沒有傳入任何東西,這個self參數從哪裡來的?
其實這是Python處理對象方法的一種操作方式。當我們調用一個類方法時,究竟是哪個實例調用了這個方法?這個信息(也就是實例引用)會自動傳遞給方法。
這就像寫成:
在這種情況下,我們告訴了bounce()方法哪個球要反彈。實際上,這個代碼也能正常工作,因為寫成myBall.bounce()時,Python在後台確實也是這麼做的。
(中場休息……)
Music Time
(接著來……)
一個示例-HotDog
下面為熱狗指定一些屬性和方法:
熱狗的屬性:
熱狗的方法:
首先,需要定義類。先定義__init__()方法,它會為熱狗設置默認屬性:
先從一個沒有加任何配料的生熱狗開始。現在建立一個方法烤熱狗:
繼續下面的工作之前,先對這一部分做個測試。首先,需要創建熱狗的一個實例,還要檢查它的屬性。
下面把這些內容都放在一個程序中:
運行這個程序,得到如下結果:
可以看到,屬性分別是cooked_level=0,cooked_string=「Raw」,condiments為空。
現在來測試cook()方法。把下面的代碼增加到上述代碼中:
再運行這個程序,現在輸出會變成:
看來我們的cook()方法能正常工作。cooked_level從0變成4,而且字元串也得到更新(從Raw變成Medium)。
下面來增加一些配料。這需要一個新的方法。另外還可以自己增加__str__()函數,讓列印對象更為容易。
這個代碼清單有點兒長,但還是建議你自己鍵入這些代碼,而且你已經有了之前的部分代碼。不過,你也可以回復「熱狗」找到這個代碼。
程序的第一部分創建了類,第二部分建立一個實例,第三部分測試了烤這個虛擬熱狗和添加配料的方法。你還可以嘗試修改上面的代碼,看看還有什麼變化!
好了,對於Python的對象你是否了解了呢?在前幾篇推文中,我們看到了:
實際上,如果仔細分析Python,幾乎一切都是對象。按編程的術語來講,我們說Python是面向對象的。這說明,Python中可以使用對象。但並不是一定得創建自己的對象,不過這樣可以讓很多事情更容易一些。
END
回顧
測試題
動手試一試
為BankAccount建立一個類定義。它應該有一些屬性,包括賬戶名(一個字元串)、賬號(一個字元串或整數)和餘額(一個浮點數),另外還要有一些方法顯示餘額、存錢和取錢。
![](https://pic.pimg.tw/zzuyanan/1488615166-1259157397.png)
![](https://pic.pimg.tw/zzuyanan/1482887990-2595557020.jpg)
※如何用 Python 爬取網頁製作電子書
※程序員學習Python必讀,你了解優缺點嗎?
TAG:Python |