天天看點

《Python面向對象程式設計指南》——1.8 複合的組合對象

本節書摘來自異步社群《python面向對象程式設計指南》一書中的第1章,第1.8節,作者[美]steven f. lott, 張心韬 蘭亮 譯,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。

為了描述21點遊戲中的發牌。以下代碼定義了hand類,用來模拟打牌政策。

在本例中,定義了一個self.dealer_card變量,值由__init__()函數傳入。可self.cards變量不基于任何參數來指派,隻是建立了一個空集合。使用如下代碼可以建立一個hand執行個體。

可是這段代碼有個缺陷,需要用好幾行代碼來構造一個hand對象。不但給序列化hand對象帶來了困難,而且再次建立對象又需要再重複以上過程。盡管再添加一個append()函數暴露給外面調用,也仍然需要很多步驟來建立集合對象。

可能會考慮使用流暢接口,但那樣并不能簡化實際問題。它隻是在建立hand對象的文法上做了一些改變。流暢接口依然會需要多個步驟來建立對象。在第2部分“持久化和序列化”中,我們需要一個接口完成類之間的調用,可以通過類中的一個函數完成,而這個函數最好是構造函數。在第9章“序列化和儲存 ——json、yaml、pickle、csv和xml”中會詳細深入介紹。

可以注意到hard_total函數和soft_total函數并沒有完全符合21點的規則。在第2章“與phthon無縫內建——基本特殊方法”中會對這個問題進行讨論。

完成組合對象的初始化

__init__()初始化方法應當傳回一個完整的對象,這樣是理想的情況。而這樣也帶來了一些複雜性,因為要建立的對象内部可能包含了集合,集合裡面又包含了其他對象。如果可以一步完成對象建立的工作這樣是最好的。

通常考慮使用一個流暢接口來完成逐個将對象添加到集合的操作,同時将集合對象作為構造函數的參數來完成初始化。

例如,如下代碼段對類的實作。

代碼中的初始化函數中完成了所有變量執行個體的指派操作。其他函數的實作都是從上一個hand類的版本中複制過來的。此處可以用兩種方式來建立hand2對象。第1種是一次加載一張牌。

第2種使用*cards參數一次加載多張牌。

第2種初始化方式給單元測試代碼帶來了便利,構造一個複合對象隻需一步。更重要的是,一步構造複合對象也有利于後續要介紹的序列化。