1. Python inspect库简介
Python inspect是Python的标准库之一,提供了许多有用的函数用于获取对象信息,包括模块、函数、类、方法、代码对象等。这些函数可以帮助我们分析、调试和了解代码的运行时行为,帮助我们更好地开发Python应用程序。
2. inspect库中常用函数介绍
2.1 inspect.getmembers()
inspect.getmembers(object[, predicate])函数返回对象object的成员,在一个列表中列出名称和值。predicate是一个可选函数,用于根据对象成员是否满足给定的条件进行筛选。如果没有提供predicate,则返回对象的所有成员。
import inspect
def func(a, b, c):
print(a, b, c)
members = inspect.getmembers(func)
print(members)
输出结果:
[('__annotations__', {}),
('__call__',
<method-wrapper '__call__' of function object at 0x0000026D4DC78E50>),
('__class__', <class 'function'>),
('__closure__', None),
('__code__',
<code object func at 0x0000026D4DC4B670, file "<ipython-input-1-422c86fa116c>", line 3>),
('__defaults__', None),
('__delattr__', <method-wrapper '__delattr__' of function object at 0x0000026D4DC78E50>),
('__dict__', {}),
('__dir__', <function func.__dir__>),
('__doc__', None),
('__eq__', <method-wrapper '__eq__' of function object at 0x0000026D4DC78E50>),
('__format__', <method '__format__' of 'function' objects>),
('__ge__', <method-wrapper '__ge__' of function object at 0x0000026D4DC78E50>),
('__get__', <method-wrapper '__get__' of function object at 0x0000026D4DC78E50>),
('__getattribute__',
<method-wrapper '__getattribute__' of function object at 0x0000026D4DC78E50>),
('__globals__',
{'__name__': '__main__',
'__doc__': 'Automatically created module for IPython interactive environment',
'__package__': None,
'__loader__': None,
'__spec__': None,
'__builtin__': <module 'builtins' (built-in)>,
'__builtins__': <module 'builtins' (built-in)>,
'_ih': ['',
'import inspect\n\ndef func(a, b, c):\n print(a, b, c)\n\nmembers = inspect.getmembers(func)\nprint(members)'],
'_oh': {},
'_dh': ['C:\\Users\\okchoo\\Documents\\python课程学习笔记'],
'In': ['',
'import inspect\n\ndef func(a, b, c):\n print(a, b, c)\n\nmembers = inspect.getmembers(func)\nprint(members)'],
'Out': {1: [('__annotations__', {}),
('__call__',
<method-wrapper '__call__' of function object at 0x0000026D4DC78E50>),
('__class__', <class 'function'>),
('__closure__', None),
('__code__',
<code object func at 0x0000026D4DC4B670, file "<ipython-input-1-422c86fa116c>", line 3>),
('__defaults__', None),
('__delattr__',
<method-wrapper '__delattr__' of function object at 0x0000026D4DC78E50>),
('__dict__', {}),
('__dir__', <function func.__dir__>),
('__doc__', None),
('__eq__', <method-wrapper '__eq__' of function object at 0x0000026D4DC78E50>),
('__format__', <method '__format__' of 'function' objects>),
('__ge__', <method-wrapper '__ge__' of function object at 0x0000026D4DC78E50>),
('__get__',
<method-wrapper '__get__' of function object at 0x0000026D4DC78E50>),
('__getattribute__',
<method-wrapper '__getattribute__' of function object at 0x0000026D4DC78E50>),
('__globals__',
{'__name__': '__main__',
'__doc__': 'Automatically created module for IPython interactive environment',
'__package__': None,
'__loader__': None,
'__spec__': None,
'__builtin__': <module 'builtins' (built-in)>,
'__builtins__': <module 'builtins' (built-in)>,
'_ih': ['',
'import inspect\n\ndef func(a, b, c):\n print(a, b, c)\n\nmembers = inspect.getmembers(func)\nprint(members)'],
'_oh': {},
'_dh': ['C:\\\\Users\\\\okchoo\\\\Documents\\\\python课程学习笔记'],
'In': ['',
'import inspect\n\ndef func(a, b, c):\n print(a, b, c)\n\nmembers = inspect.getmembers(func)\nprint(members)'],
'Out': {1: [('__annotations__', {}),
('__call__',
<method-wrapper '__call__' of function object at 0x0000026D4DC78E50>),
('__class__', <class 'function'>),
('__closure__', None),
('__code__',
<code object func at 0x0000026D4DC4B670, file "<ipython-input-1-422c86fa116c>", line 3>),
('__defaults__', None),
('__delattr__',
<method-wrapper '__delattr__' of function object at 0x0000026D4DC78E50>),
('__dict__', {}),
('__dir__', <function func.__dir__>),
('__doc__', None),
('__eq__', <method-wrapper '__eq__' of function object at 0x0000026D4DC78E50>),
('__format__', <method '__format__' of 'function' objects>),
('__ge__', <method-wrapper '__ge__' of function object at 0x0000026D4DC78E50>),
('__get__',
<method-wrapper '__get__' of function object at 0x0000026D4DC78E50>),
('__getattribute__',
<method-wrapper '__getattribute__' of function object at 0x0000026D4DC78E50>),
('__globals__',
{...},
('__hash__',
<method-wrapper '__hash__' of function object at 0x0000026D4DC78E50>),
('__init__',
<method-wrapper '__init__' of function object at 0x0000026D4DC78E50>),
('__init_subclass__', <built-in method __init_subclass__ of type object at 0x00007FFBE86FE6F0>),
('__kwdefaults__', None),
('__le__', <method-wrapper '__le__' of function object at 0x0000026D4DC78E50>),
('__lt__', <method-wrapper '__lt__' of function object at 0x0000026D4DC78E50>),
('__module__', '__main__'),
('__name__', 'func'),
('__ne__', <method-wrapper '__ne__' o...
输出结果显示了函数func的所有成员,包括函数名、对应的方法等。注意到在输出结果中,方法名前有双下划线和后面的双下划线,这是Python中的特殊方法。
2.2 inspect.getargspec()
inspect.getargspec(func)函数返回函数func的参数信息,包括参数名、默认值等。
import inspect
def func(a, b=1, *args, **kwargs):
pass
argspec = inspect.getargspec(func)
print(argspec)
输出结果:
ArgSpec(args=['a', 'b'], varargs='args', varkw='kwargs', defaults=(1,))
这段代码中的func定义了多个参数,使用getargspec()函数可以获取到函数的参数信息,其中args列表中存储了函数的位置参数,varargs和varkw则分别对应函数的可变长位置参数和可变长关键字参数,这种方式非常有用,可以让我们更好地理解函数的参数。
2.3 inspect.signature()
inspect.signature(func)函数返回一个inspect.Signature类的实例,利用该实例可以访问函数的参数。Signature类提供了非常友好的API,可以让我们方便地查看函数的参数信息,还可以非常方便地将函数的参数打包成一个字典,以便于后续操作。
def func(a, b=1, *args, **kwargs):
pass
signature = inspect.signature(func)
print(signature)
params = signature.parameters
for name, param in params.items():
print(name, param.kind, param.default)
输出结果:
(a, b=1, *args, **kwargs)
a POSITIONAL_OR_KEYWORD None
b POSITIONAL_OR_KEYWORD 1
args VAR_POSITIONAL None
kwargs VAR_KEYWORD None
输出结果中,可以看到函数的所有参数及其对应的类型。其中,param.kind对应的是参数的类型,可选值为POSITIONAL_ONLY、POSITIONAL_OR_KEYWORD、VAR_POSITIONAL、KEYWORD_ONLY、VAR_KEYWORD。如果参数是位置参数,则kind的值为POSITIONAL_OR_KEYWORD;如果参数是可变长位置参数,则kind的值为VAR_POSITIONAL;如果参数是可变长关键字参数,则kind的值为VAR_KEYWORD。
3. inspect库的一些常见应用场景
3.1 查看模块导入路径
有时候我们可能需要查看一个模块的导入路径,以保证它能够被正确地进行导入并被使用。Python inspect库中的findsource()函数可以帮助我们实现这个目标。
import inspect
import os
import numpy
print(inspect.getfile(os)) # 查看os模块路径
print(inspect.getfile(numpy)) # 查看numpy模块路径
输出结果:
C:\\Python\\Python36\\lib\\os.py
C:\\Python\\Python36\\lib\\site-packages\\numpy\\__init__.py
可以看到输出结果中包含两个绝对路径,它们分别表示os模块和numpy模块的路径,这些路径是Python在我们的计算机上找到这些模块的路径。
3.2 获取函数或方法类型
Python中的函数和方法在实际工作中通常都有着不同的使用场景。在使用inspect库的isfunction()和ismethod()函数时,我们可以轻松获取函数或方法的类型。
class MyClass:
def my_method(self):
pass
def my_function():
pass
obj = MyClass()
print(inspect.isfunction(my_function))
print(inspect.isfunction(obj.my_method))
print(inspect.ismethod(obj.my_method))
输出结果:
True
False
True
上述结果中,我们注意到函数my_function是函数类型,但是方法my_method则不是函数类型,而是方法类型(即method),这是因为方法是属于类的一种成员,它通常需要一个类实例来进行调用并访问类属性。
3.3 函数调用与跟踪
inspect库还可以用于函数调用与跟踪,这对于调试和分析代码非常有用。
import inspect
def func(a, b):
c = a ** b
return c
def trace_calls(frame, event, arg):
if event != 'call':
return
co = frame.f_code
func_name = co.co_name
filename = co.co_filename
line_no = frame.f_lineno
print(f'Call to {func_name} on line {line_no} of {filename}')
return
sys.settrace(trace_calls)
func(3, 4)
sys.settrace(None)
输出结果:
Call to func on line 3 of <ipython-input-7-409add4bb7cc>
Call to func on line 4 of <ipython-input-7-409add4bb7cc>
Call to func on line 5 of <ipython-input-7-409add4bb7cc>
在上述代码中,我们定义了一个函数来计算a**b,然后对它进行了跟踪,最终得到了一些关于函数调用情况的信息,包括函数名、行号和文件名等,这些信息可以帮助我们更好地理解Python代码的开发过程。
4. 总结
Python inspect库是Python中一个非常强大的库,它让我们可以轻松获取Python对象的信息,包括模块、函数、类、方法、代码对象等,并提供了许多函数用于调试和了解代码的运行时行为。本文主要介绍了inspect库中几个常用的函数以及它们的应用场景,这些函数包括getmembers、getargspec、signature等,而它们的使用对于更好地理解Python代码和提高代码开发效率非常有帮助。