前面內容我們使用inspect模塊獲取了模塊、類、函數的詳細信息和幫助文檔以及一個類的層次結構。今天,我們來看下如何使用inspect模塊獲取模塊、類、方法、函數的原始碼。
獲取方法
通過下面方法獲取原始碼及位置信息
inspect.getsource(obj)
參數可以是模塊(models)、類(class)、方法(method)、函數(function)、回溯(traceback)、幀(frame),或代碼(code)對象。原始碼作為單個字符串被返回。如果傳入的對象原始碼沒有獲取成功,則會引發OSError異常。
inspect.getsourcelines(obj)
參數同getsource()方法。它返回的原始碼作為行列表返回,行號指示原始源文件找到第一行代碼。如果無法檢索原始碼,則引發OSError異常。
inspect.getsourcefile(obj)
返回可用於定位對象源的文件名。如果無法識別獲取源,則返回None。
如何使用
上面3個方法如何使用呢?
我們還是使用前面自定義的demo模塊,如果沒有,請從《新手入門到進階,你不可不知的模塊,用Python獲取對象的詳細信息》一文中複製粘貼,或者粘貼下面的結果測試。
返回模塊原始碼
import inspect
import demo
print(inspect.getsource(demo))
>>>
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:bob
# ProjectName : bowen
# DefaultFileName : demo.py
# User : Administrator
# Time : 2020/1/7 22:45
# IDEName : PyCharm
"""這是一個示例模塊,用於測試inspect模塊
"""
def module_level_function(arg1, arg2='default', *args, **kwargs):
"""這個函數是在模塊中定義的函數."""
local_variable = arg1 * 2
return local_variable
class A(object):
"""模塊中的自定義類A"""
def __init__(self, name):
self.name = name
def get_name(self):
"返回類的實例的名稱"
return self.name
instance_of_a = A('一個實例')
class B(A):
"""這是類B
它繼承自A類.
"""
# 這個方法是B類獨有的方法.
def do_something(self):
"""B類的實例提供的接口"""
pass
def get_name(self):
"重寫了A類的方法"
return 'B(' + self.name + ')'
成功獲取demo.py的原始碼。
它不僅以字符串方式展現了類的原始碼,還保留了類中的縮進(博文中將縮進去除了,感興趣的小夥伴自己在編譯器中看)。這點很好,方便我們學習……
獲取類的原始碼
print(inspect.getsource(demo.A))
>>>
class A(object):
"""模塊中的自定義類A"""
def __init__(self, name):
self.name = name
def get_name(self):
"返回類的實例的名稱"
return self.name
成功返回類A的原始碼!
獲取方法的原始碼
print(inspect.getsource(demo.A.get_name))
>>>
def get_name(self):
"返回類的實例的名稱"
return self.name
上面代碼仍然是保留縮進的。
如果你試圖返回類的實例(比如demo.py中定義的instance_of_a)的原始碼,則會拋出TypeError異常。異常內容如下:
「TypeError: module, class, method, function, traceback, frame, or code object was expected, got A」
等等,這裡就不一一例舉了。下面來看下getsourcelines()方法有何不同
逐行返回getsourcelines()
print(inspect.getsourcelines(demo.A.get_name))
結果如下圖
使用
print(len(inspect.getsourcelines(demo.A.get_name)[0]))返回方法具體行數信息
print(inspect.getsourcelines(demo.A.get_name)[1])返回方法在模塊中的位置
這個功能對於讀取模塊中的內容很有用處,感興趣的小夥伴可以深入研究一下。
對於inspect.getsourcefile(obj)方法返回obj對象位置(字符串對象)
import os
import inspect
print(inspect.getsourcefile(os))
>>>
D:\ProgramData\Anaconda3\lib\os.py
你什麼時候如果想找原始碼讀讀,這個函數很有用哦!
都能獲得原始碼?
先不要高興得太早了,大家不要以為這個模塊什麼原始碼都可以獲取。其實不然,如下例:
import inspect
import os
print(inspect.getsource(os)[:10])
>>>
r"""OS rou
成功獲取,但是,如果要想知道其中某一方法的實現,就會拋出TypeError異常,如下
print(inspect.getsource(os.getcwd))
異常如下
>>>
TypeError: module, class, method, function, traceback, frame, or code object was expected, got builtin_function_or_method
意思是類型錯誤:需要模塊、類、方法、函數、回溯、幀或代碼對象,而我們傳入到函數中的是一個內置函數或方法(builtin_function_or_method)
結論
模塊、類、方法、函數、回溯、幀或代碼對象的原始碼可以通過inspect.getsource()或者inspect.getsourcelines()獲得,但是對於內置函數或方法我們無法通過這兩個函數獲取其原始碼內容。
好了,今天的內容就到這裡了,喜歡Python編程的小夥伴們試試看!還有什麼模塊能獲取到內置函數或方法的原始碼呢
轉載請註明出處,百家號:Python高手養成