Python怎樣用C實現對象的多態性

來源:互聯網
上載者:User

        在Python中,一切皆為對象,所有的對象都有一些相同的內容,在PyObject中定義。

        //xk> 怎樣實現繼承

        PyObject是Python中一切(new style)類的基類,其定義非常簡單

//xk> Python3.2.2_Source/Include/Object.h
typedef struct _object {
    _PyObejct_HEAD_EXTRA
    Py_ssize_t ob_refcnt; //xk> reference count
    struct _typeobject *ob_type; //xk> object的類型用type object來表示
} PyObject;

_PyObejct_HEAD_EXTRA宏不用管,在發布版Python中沒有編譯。PyObject結構體中僅僅定義了引用計數和類型資訊。對象的類型也是對象(typedef _typeobject{...}PyTypeObject;),用類型對象來表示類型資訊。

        怎麼用C語言實現繼承關係呢?子類繼承了父類的內容,並有所增改,所以在記憶體布局上,只要把父類的內容放在對象的頭部,就可以用父類指標指向子類對象。在Python內部,每個對象都有相同的對象頭部——PyObejct的內容,這就使得在Python內部,對對象的引用變得非常統一,只需要用一個PyObject *指標就可以引用任意的對象。這對於實現多態是必要的。

        //xk> 怎樣表示類型

        對象的類型定義了對象的資料成員和能夠施加在對象之上的操作。查看Python3.2.2_Source/Include/Object.h中對_typeobejct的定義(內容非常多,不能在這裡全部帖出來),包含了大量的函數指標。這些函數指標即表示該類型所定義的操作,亦即表示該類型的對象在運行時所表現的行為。

        在這些操作資訊中,有三個指標比較重要:tp_as_number, tp_as_sequence, tp_as_mapping。以tp_as_number為例,它是PyNumberMethonds *指標,而PyNumberMethonds結構體定義了作為一個數值對象應該支援的操作。類似的,tp_as_sequence表示作為一個序列對象所支援的操作;tp_as_mapping表示作為一個關聯對象所支援的操作。可見:在Python中,一個對象可以同時是數值對象、序列對象、關聯對象,關鍵看它支援哪些操作,也就是定義了哪些非NULL的函數指標。因此,Python對象的多態性是基於行為的,而不像C++/Java等語言中多態性是基於類型的。Python對象實際上是全類型的,可以有的函數指標全部都有,只不過很多函數指標都是NULL,只要你實現了該函數,python對象就能表現出該行為。

>>> class MyInt(int):
            def __getitem__(self, key):
                return key + str(self)

>>> a = MyInt(1)
>>> b = MyInt(2)
>>> print a + b
3
>>> a['key']
'key1'

定義了一個子類從內建的int類繼承而來,應該是數值對象,但是因為通過定義__getitem__方法,將MyInt在Python內部對應的PyTypeObejct對象中原本為NULL的函數指標重新賦值,使得該類型的對象能夠表現出關聯對象的特性。

        //xk> Python對象的多態性

        通過PyObject和PyTypeObejct,Python利用C語言實現了類似C++所提供的對象多態性(但是有所不同)。在Python中建立一個對象比如PyIntObject對象時,Python內部是用PyObject *指標而不是PyIntObject *指標來儲存和維護這個對象,在Python內部各個函數之間傳遞的都是一種泛型指標——PyObject *,因此無法根據指標類型判斷所指的對象究竟是個什麼類型,只能從指標所指對象的ob_type域動態地進行判斷。由此,Python實現了多態機制。

        //xk> 亂彈:C哲學和C++哲學的比較

        C哲學:保持簡單。

        C++哲學:用複雜的工具對付複雜的現實問題,以此擷取解決方案的簡單直接。

        C和C++都意識到程式設計的本質問題是控制複雜度,只不過它們採用了不同的思路。

        C語言選擇用分治法,模組化將一個複雜問題分解成許多相對簡單的小問題,並精心設計模組之間的通訊。這裡的模組可以是一個函數、一個進程甚至一個獨立的程式。Unix工具鏈哲學與此一脈相承。

        《C++沉思錄》中闡明:類似汽車製造等傳統工業,一方面使用者介面越來越簡單,另一方面內部實現越來越複雜。我們生活在一個如此複雜的世界裡,因此Java和C#也不可避免地變得越來越複雜。C++的複雜源於要解決的現實問題的複雜。

        從理論上爭論孰優孰劣是毫無意義的,兩者都很有道理。C語言的選擇有一定的問題,從整體來看模組化的設計容易導致多餘(Python的每個對象都要定義對所有類型的操作的支援,大量的函數指標被設定為NULL),用C來實現物件導向的機制明顯不如C++簡單直接。雖然如此,C語言貌似要比C++受到更廣泛的支援。C++貌似真的過於複雜了,既難於學習,開發效率又低。在面對非常非常複雜的問題時,從整體上來把握對操刀者提出了很高的要求,分而治之雖然難免冗餘,好歹能夠可行。

        最後說一句,對學生來說,選擇哪個都沒有錯,餓死於乾草堆之間才是最大的愚蠢。學習盡量與手頭上的項目結合,把手上看似平淡無奇的事情做得比別人深入一步,learn by doing it.

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.