Python中inspect模塊 代碼自省inspect的元編程實用技巧

inspect模塊在python中用于分析和操作代碼結(jié)構(gòu),能獲取函數(shù)名、調(diào)用、參數(shù)簽名、類成員及源碼等信息。1.使用inspect.stack()可獲取調(diào)用棧信息,如當(dāng)前函數(shù)被誰調(diào)用;2.inspect.signature()可動態(tài)分析函數(shù)參數(shù),適用于編寫通用裝飾器;3.inspect.getmembers()可用于檢查類的方法與屬性;4.inspect.getsource()等函數(shù)可讀取源碼或文檔字符串,適合生成文檔或調(diào)試。這些功能在元編程、框架開發(fā)和調(diào)試中非常實用。

python中,inspect模塊是一個非常強大的工具,它能讓你“看穿”代碼本身。尤其是在做元編程、調(diào)試或者寫框架時,掌握一些inspect的實用技巧可以幫你省去不少麻煩。

下面幾個場景,就是你在日常開發(fā)中可能會遇到的問題,以及如何用`inspect模塊巧妙解決的方法。


獲取當(dāng)前函數(shù)名或調(diào)用棧信息

有時候你想知道某個函數(shù)被誰調(diào)用了,或者想打印出當(dāng)前執(zhí)行的函數(shù)名用于調(diào)試,這時候就可以用inspect.stack()。

import inspect  def who_called_me():     caller = inspect.stack()[1]     print(f"被 {caller.function} 在第 {caller.lineno} 行調(diào)用")  def test():     who_called_me()  test()

這樣你就能快速定位到是誰調(diào)用了這個函數(shù)。這在調(diào)試大型項目的時候特別有用,尤其是當(dāng)你不確定某個函數(shù)是從哪里被觸發(fā)的。

立即學(xué)習(xí)Python免費學(xué)習(xí)筆記(深入)”;

常用操作:

  • inspect.currentframe():獲取當(dāng)前幀對象
  • inspect.getouterframes():獲取調(diào)用棧的所有幀
  • inspect.getframeinfo():獲取幀的信息,比如文件名、行號等

動態(tài)分析函數(shù)參數(shù)和簽名

你有沒有遇到過這樣的情況:你寫了一個裝飾器,但希望它能自動適配不同參數(shù)的函數(shù)?這時候inspect.signature()就派上用場了。

from inspect import signature  def my_decorator(func):     sig = signature(func)     print(f"函數(shù) {func.__name__} 的參數(shù)是:{sig}")     def wrapper(*args, **kwargs):         return func(*args, **kwargs)     return wrapper  @my_decorator def example(a, b=2):     pass

輸出結(jié)果會告訴你這個函數(shù)有兩個參數(shù),一個是必填的a,一個是默認值為2的b。你可以基于這些信息做更智能的參數(shù)處理,比如驗證類型、生成文檔等。

關(guān)鍵點:

  • signature.parameters:返回一個有序字典,包含所有參數(shù)
  • 可以判斷參數(shù)類型(positional-only、keyword-only、varargs等)
  • 適用于編寫通用性強的裝飾器或插件系統(tǒng)

檢查類和對象的結(jié)構(gòu)信息

如果你在做反射或者動態(tài)加載模塊,可能需要檢查一個類有哪些方法、屬性,或者判斷一個對象是否是某種類型。

import inspect  class MyClass:     def method_one(self):         pass      def method_two(self):         pass  methods = inspect.getmembers(MyClass, predicate=inspect.isfunction) print(methods)

這段代碼會列出MyClass中的所有方法。你也可以換成其他predicate,比如ismethod、ismethoddescriptor等來篩選不同的成員。

常見用途包括:

  • 自動生成API文檔
  • 構(gòu)建插件系統(tǒng)(自動發(fā)現(xiàn)模塊中的類或方法)
  • 調(diào)試時查看對象內(nèi)部結(jié)構(gòu)

查看源碼和注釋內(nèi)容

你還可以用inspect直接讀取函數(shù)或類的源碼,這對于調(diào)試或生成文檔很有幫助。

import inspect  def sample_func(x: int, y: str) -> bool:     """示例函數(shù)"""     return x > 0 and y != ""  source = inspect.getsource(sample_func) print(source)

除了getsource,還有幾個相關(guān)函數(shù):

  • getdoc():獲取對象的文檔字符串(docstring)
  • getcomments():獲取源碼頂部的注釋
  • getfile():獲取定義該對象的文件路徑

這對自動生成文檔、分析代碼結(jié)構(gòu)非常有幫助,尤其適合寫自動化工具鏈時使用。


基本上就這些。雖然inspect模塊看起來不是每天都要用的東西,但在做一些高級功能(比如寫框架、自動化測試、調(diào)試工具)時,它確實能幫你節(jié)省不少時間。關(guān)鍵是理解它的各個函數(shù)能做什么,然后根據(jù)實際需求靈活組合使用。

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點贊14 分享