<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            5.3. 類的定義

            Python 是完全面向對象的:你可以定義自已的類,從自已的或內置的類繼承,然后從你定義的類創建實例。

            Python 中定義類很簡單。就像定義函數,沒有單獨的接口定義。只要定義類,然后就可以開始編碼。Python 類以保留字 class 開始,后面跟著類名。從技術上講,有這些就夠了,因為一個類并非必須從其它類繼承。

            例 5.3. 最簡單的 Python

            
            class Loaf: 1
                pass    2 3
            1 這個類的名字是 Loaf,它沒有從其它類繼承。類名通常是第一個字母大寫,如:EachWordLikeThis,但這只是一個習慣,不是一個必要條件。
            2 這個類沒有定義任何方法或屬性,但是從語法上,需要在定義中有些東西,所以你使用 pass。這是一個 Python 保留字,僅僅表示 “向前走,不要往這看”。它是一條什么都不做的語句,當你刪空函數或類時,它是一個很好的占位符。
            3 你可能猜到了,在類中的所有東西都要縮近,就像位于函數、if 語句,for 循環,諸如此類的代碼。第一條不縮近的東西不屬于這個類。
            注意
            Python 中的 pass 語句就像 JavaC 中的大括號空集 ({})。

            當然,實際上大多數的類都是從其它的類繼承來的,并且它們會定義自已的類方法和屬性。但是就像你剛才看到的,除了名字以外,類沒有什么必須要具有的。特別是,C++ 程序員可能會感到奇怪,Python 的類沒有顯示的構造函數和析構函數。Python 類的確存在與構造函數相似的東西:__init__ 方法。

            例 5.4. 定義 FileInfo

            
            from UserDict import UserDict
            
            class FileInfo(UserDict): 1
            1 Python 中,類的基類只是簡單地列在類名后面的小括號里。所以 FileInfo 類是從 UserDict 類 (它是從 UserDict 模塊導進來的) 繼承來的。UserDict 是一個像字典一樣工作的類,它允許你完全子類化字典數據類型,同時增加你自已的行為。{也存在相似的類 UserListUserString ,它們允許你子類化列表和字符串。)[2] 在這個類的背后有一些“巫術”,我們將在本章的后面,隨著更進一步地研究 UserDict 類,揭開這些秘密。
            注意
            Python 中,類的基類只是簡單地列在類名后面的小括號里。不像在 Java 中有一個特殊的 extends 關鍵字。

            Python 支持多重繼承。在類名后面的小括號中,你可以列出許多你想要的類名,以逗號分隔。

            5.3.1. 初始化并開始類編碼

            本例演示了使用 __init__ 方法來進行 FileInfo 類的初始化。

            例 5.5. 初始化 FileInfo

            
            class FileInfo(UserDict):
                "store file metadata"              1
                def __init__(self, filename=None): 2 3 4
            1 類也可以 (并且應該) 有 doc strings ,就像方法和函數一樣。
            2 __init__ 在類的實例創建后被立即調用。它可能會引誘你稱之為類的構造函數,但這種說法并不正確。說它引誘,是因為它看上去像 (按照習慣,__init__ 是類中第一個定義的方法),行為也像 (在一個新創建的類實例中,它是首先被執行的代碼),并且叫起來也像 (“init”當然意味著構造的本性)。說它不正確,是因為對象在調用 __init__ 時已經被構造出來了,你已經有了一個對類的新實例的有效引用。但 __init__ 是在 Python 中你可以得到的最接近構造函數的東西,并且它也扮演著非常相似的角色。
            3 每個類方法的第一個參數,包括 __init__,都是指向類的當前實例的引用。按照習慣這個參數總是被稱為 self。在 __init__ 方法中,self 指向新創建的對象;在其它的類方法中,它指向方法被調用的類實例。盡管當定義方法時你需要明確指定 self,但在調用方法時,你 用指定它,Python 會替你自動加上的。
            4 __init__ 方法可以接受任意數目的參數,就像函數一樣,參數可以用缺省值定義,即可以設置成對于調用者可選。在本例中,filename 有一個缺省值 None,即 Python 的空值。
            注意
            習慣上,任何 Python 類方法的第一個參數 (對當前實例的引用) 都叫做 self。這個參數扮演著 C++Java 中的保留字 this 的角色,但 selfPython 中并不是一個保留字,它只是一個命名習慣。雖然如此,也請除了 self 之外不要使用其它的名字,這是一個非常堅固的習慣。

            例 5.6. 編寫 FileInfo

            
            class FileInfo(UserDict):
                "store file metadata"
                def __init__(self, filename=None):
                    UserDict.__init__(self)        1
                    self["name"] = filename        2
                                                   3
            1 一些偽面向對象語言,像 Powerbuilder 有一種“擴展”構造函數和其它事件的概念,即父類的方法在子類的方法執行前被自動調用。Python 不是這樣,你必須顯示地調用在父類中的合適方法。
            2 我告訴過你,這個類像字典一樣工作,那么這里就是第一個印象。我們將參數 filename 賦值給對象 name 關鍵字,作為它的值。
            3 注意 __init__ 方法從不返回一個值。

            5.3.2. 了解何時去使用 self__init__

            當定義你自已的類方法時,你必須 明確將 self 作為每個方法的第一個參數列出,包括 __init__。當從你的類中調用一個父類的一個方法時,你必須包括 self 參數。但當你從類的外部調用你的類方法時,你不必對 self 參數指定任何值;你完全將其忽略,而 Python 會自動地替你增加實例的引用。我知道剛開始這有些混亂,它并不是自相矛盾的,因為它依靠于一個你還不了解的區別 (在綁定與非綁定方法之間),故看上去是矛盾的。

            噢。我知道有很多知識需要吸收,但是你要掌握它。所有的 Python 類以相同的方式工作,所以一旦你學會了一個,就是學會了全部。如果你忘了別的任何事,也要記住這件事,因為我認定它會讓你出錯:

            注意
            __init__ 方法是可選的,但是一旦你定義了,就必須記得顯示調用父類的 __init__ 方法 (如果它定義了的話)。這樣更是正確的:無論何時子類想擴展父類的行為,后代方法必須在適當的時機,使用適當的參數,顯式調用父類方法。

            Footnotes

            [2] 在 2.2 之后已經可以從 dict、list 來派生子類了,關于這一點作者在后文也會提到。――譯注

            <span id="7ztzv"></span>
            <sub id="7ztzv"></sub>

            <span id="7ztzv"></span><form id="7ztzv"></form>

            <span id="7ztzv"></span>

                  <address id="7ztzv"></address>

                      亚洲欧美在线