對Python應用程序進行剖析解讀
Python應用程序是一個真正面向對象的語言,它只增加了很少的新語法就實現了類,它的類機制是C++ 和Modula-3的類機制的混合,Python的類并不嚴格限制用戶對定義的修改,它依賴于用戶自覺不去修改定義。
類繼承機制允許多個基類的繼承,導出類可以重載基類的任何方法,方法可以調用基類的同名方法。對象可以包含任意多的私有數據。用C++術語說,所有類成員(包括數據成員)是公用的,所有成員函數是虛擬(virtual)的。沒有特別的構建函數或銷毀函數(destructor)。
如同在Modula-3中一樣,從對象的方法中要引用對象成員沒有簡捷的辦法:方法函數的必須以對象作為第一個參數,而在調用時則自動提供。象在Smalltalk中一樣,類本身也是對象,實際上這里對象的含義比較寬:在Python 中所有的數據類型都是對象。
象在C++或Modula-3中一樣,內置類型不能作為基類由用戶進行擴展。并且,象C++但不象Modula-3,多數有特殊語法的內置函數(如算術算符、下標等)可以作為類成員重定義。
Python應用程序的對象概念比較廣泛,對象不一定非得是類的實例,因為如同C++和Modula-3而不同于Smalltalk,Python的數據類型不都是類。比如基本內置類型整數、列表等不是類,甚至較古怪的類型如文件也不是類。然而,Python所有的數據類型都或多或少地帶有一些類似對象的語法。
對象是有單獨身份的,同一對象可以有多個名字與其聯系,這在其他語言中叫做別名。這樣做的好處乍一看并不明顯,而且對于非可變類型(數字、字符串、序表(tuple))等沒有什么差別。
但是別名句法對于包含可變對象如列表、字典及涉及程序外部物件如文件、窗口的程序有影響,這可以有利于程序編制。在引入類之前,我們必須講一講Python的作用域規則。類定義很好地利用了名字空間,需要了解Python如何處理作用域和名字空間才能充分理解類的使用。另外,作用域規則也是一個高級Python程序員必須掌握的知識。
因為別名有些類似指針:比如,傳遞一個對象變得容易,因為這只是傳遞了一個指針;如果一個函數修改了作為參數傳遞來的對象,修改結果可以傳遞回調用處。這樣就不必象Pascal那樣使用兩種參數傳遞機制。
名字空間是從名字到對象的映射。多數名字空間目前是用Python字典類型實現的,不過這一點一般是注意不到的,而且將來可能會改變。下面是名字空間的一些實例:Python中內置的名字(如abs()等函數,以及內置的例外名);模塊中的全局名;函數調用中的局部變量名。
在某種意義上一個對象的所有屬性也構成了一個名字空間。關于名字空間最重要的事要知道不同名字空間的名字沒有任何聯系;例如,兩個不同模塊可能都定義了一個叫“maximize ”的函數而不會引起混亂,因為模塊的用戶必須在函數名之前加上模塊名作為修飾。
另外,在Python應用程序中可以把任何一個在句點之后的名字稱為屬性,例如,在表達式z.real中,real是一個對象z的屬性。嚴格地說,對模塊中的名字的引用是屬性引用:在表達式modname.funcname 中,modname是一個模塊對象,funcname是它的一個屬性。
在這種情況下在模塊屬性與模塊定義的全局名字之間存在一個直接的映射:它們使用相同的名字空間!屬性可以是只讀的也可以是可寫的。在屬性可寫的時候,可以對屬性賦值。
名字空間與不同時刻創建,有不同的生存周期。包含Python內置名字的名字空間當Python 解釋程序開始時被創建,而且不會被刪除。模塊的全局名字空間當模塊定義被讀入時創建,一般情況下模塊名字空間也一直存在到解釋程序退出。由解釋程序的最頂層調用執行的語句。
不論是從一個腳本文件讀入的還是交互輸入的,都屬于一個叫做__main__的模塊,所以也存在于自己的全局名字空間之中。(內置名字實際上也存在于一個模塊中,這個模塊叫做__builtin__ )。
函數的局部名字空間當函數被調用時創建,當函數返回或者產生了一個不能在函數內部處理的例外時被刪除。(實際上,說是忘記了這個名字空間更符合實際發生的情況。)當然,遞歸調用在每次遞歸中有自己的局部名字空間。
一個作用域是Python應用程序中的一個文本區域,其中某個名字空間可以直接訪問。“直接訪問” 這里指的是使用不加修飾的名字就直接找到名字空間中的對象,雖然作用域是靜態定義的,在使用時作用域是動態的。
在任何運行時刻,總是恰好有三個作用域在使用中(即恰好有三個名字空間是直接可訪問的):最內層的作用域,最先被搜索,包含局部名字;中層的作用域,其次被搜索,包含當前模塊的全局名字;最外層的作用域最后被搜索,包含內置名字。
【編輯推薦】