Python中的“黑科技”:內省(Introspection)與反射(Reflection)

內省與反射對於編程語言來說,是非常重要的特性,對Python同樣如此。如果靈活運營,可以大大提高我們對代碼的掌控能力。今天,小編就來帶大家看一看Python中的這兩項“黑科技”。

Python中的“黑科技”:內省(Introspection)與反射(Reflection)

內省

內省,有時也叫類型內省,是在運行時進行的一種對象檢測機制。我們可以通過內省來獲取一個對象的所有信息,比如這個對象的類型,其中包含哪些屬性等等。讓我們來看兩個例子:

例子1:dir()

dir()是內省機制中的一個重要內置函數。這個函數可以將一個對象的所有屬性以字符串列表的形式返回。

Python中的“黑科技”:內省(Introspection)與反射(Reflection)

這段代碼的輸出為:

>>> ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'foo', 'get_foo']

在這些屬性當中,除了我們自己定義的“foo”和“get_foo”以外,其它的都是Python對象自帶的屬性。

例子2:類型檢查

類型檢查的方法有很多種,比如:

Python中的“黑科技”:內省(Introspection)與反射(Reflection)

注意,在使用isinstance()時有一個坑,那就是對於有繼承關係的兩個類,它的結果始終是True。

比如下面這兩個類,logging.FileHandler繼承自logging.StreamHandler。儘管這兩個類並不相同,但是isinstance()的結果是True。

Python中的“黑科技”:內省(Introspection)與反射(Reflection)

除了上面舉的例子,Python中利用內省還能做很多事情。下面,我們用inspect模塊來實現一個很二的功能:用一個裝飾器來檢測一個對象是類還是函數。

Python中的“黑科技”:內省(Introspection)與反射(Reflection)

反射

與內省相比,反射的功能要顯得更為強大。反射使得程序具有在運行時動態修改自己的結構和行為的能力。繼續來看幾個例子:

例子1:動態設置屬性

假設有一個空模塊,現在我們想把所有的環境變量作為屬性添加到這個模塊中。這個文件env.py可以這樣實現:

Python中的“黑科技”:內省(Introspection)與反射(Reflection)

import_module(__name__) 把當前模塊作為一個對象返回,setattr() 將環境變量的key,value值作為屬性添加到模塊中去。

事實上,import_module(__name__)也是利用裡Python的反射能力。它根據輸入的字符串參數生成了一個模塊對象。

例子2:用getattr()動態獲取屬性值

在另一個文件output.py中,我們導入env.py,然後實現一個函數,獲取其中的所有環境變量參數並以字典的形式返回:

Python中的“黑科技”:內省(Introspection)與反射(Reflection)

內置函數getattr()允許我們根據屬性名來獲取屬性的值。

例子3:動態方法

下面小編要放大招了。我們要實現一個動態方法,當這個方法被調用時,它甚至都還沒有被定義,但是仍然能夠被成功調用。這是如何實現的呢?我們來看代碼:

Python中的“黑科技”:內省(Introspection)與反射(Reflection)

這段代碼看起來可能有點燒腦。總的來說,我們創建了一個GreetMe對象,並且依次調用其hello(),bye()和nice_to_meet_you()方法。然而,這三個方法在GreetMe類中均沒有定義。

這裡面的關鍵在於__getattr__() 方法。在Python中,當一個沒有被定義的方法被訪問時,__getattr__() 就會被調用。後面的事情就靠大家自己去理解了。

好了,今天的“黑科技”就先講到這裡。感興趣的小夥伴可以留言交流。

感謝大家的閱讀!


分享到:


相關文章: