1. 程式人生 > >python中的反射和自省

python中的反射和自省

本文主要介紹python中的反射和自省,以及該機制的簡單應用

熟悉JAVA的程式設計師,一定經常和Class.forName打交道。即使不是經常親自呼叫這個方法,但是在很多框架中(Springeclipse plugin機制)都依賴於JAVA的發射和自省能力。而在python中,也同樣有著強大的反射和自省能力,本文將做簡單的介紹。

<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

首先看一下自省,介紹一下幾個重要的函式:

dir函式,傳入的引數是物件,返回該物件的所有屬性和函式列表:

如:

<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />

可以看到,string物件的所有函式,屬性都列舉出來了。

getattr方法,傳入引數是物件和該物件的函式或者屬性的名字,返回物件的函式或者屬性例項,如下:

 

 

 

callable方法,如果傳入的引數是可以呼叫的函式,則返回true,否則返回false

 

下面這段程式碼列出物件所有函式:

methodList = [method for method in dir(object) if callable(getattr(object,method))]

比如檢視string的所有函式:

 

接下來,看看python的是如何體現反射的。

globals()

這個函式返回一個map,這個mapkey是全域性範圍內物件的名字,value是該物件的例項。

在不匯入任何module下,執行globals()的結果如下:

 

在匯入sys後,可以發現,globals()返回的map中,多了sys module

 

 

在匯入sgmllib,如下:

如果匯入類後,在map中,可以找到類。

 

 

所以,只要將class的名字最為key,即可得到class。如下:

 

而如果要例項化一個物件,可以如下:

這樣,實現了類似

java中,Class.forName().newInstance()的功能。但是,在使用globals函式之前,還需要匯入相應的類,如果不匯入,而直接使用globals[‘...’]查詢這個類,則會丟擲異常。

所以,我在介紹一種可以動態匯入的方法。

首先,介紹一個函式 __import__, 這個函式傳入的引數是module的名字,返回這個module,然後,在結合之前介紹過的getattr,於是,我們可以寫出下面兩句程式碼,實現物件的自省。

由此可見,python提供的反射和自省機制是十分便捷的。這也方便了很多操作。比如,如下這段程式碼,將匯入指令碼檔案所在資料夾下的所有測試檔案(以test結尾的指令碼檔案0,並進行測試。

程式碼出自dive in python(這本書寫的很好),比較容易理解,不做詳細介紹了。主要是先獲得目錄,然後過濾出符合條件的指令碼檔案,去掉字尾名,作為模組載入。