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ù)實際需求靈活組合使用。