Python inspect模块详解:获取对象信息与源码分析
本文详细介绍Python标准库inspect模块的核心功能,包括如何获取函数和类的参数信息、提取源代码及判断对象类型。重点解析getargspec方法处理*args和**kwargs的技巧,以及通过字节码co_flags属性判断特殊参数的实现原理,帮助开发者深入理解Python对象反射机制。
inspect模块主要用于收集Python对象的相关信息,能够获取类或函数的参数详情、源码内容、堆栈解析以及进行对象类型检查等。该模块提供了一些实用方法,具体如下:
文档说明如下:
The inspect module provides several useful functions to help get information about live objects such as modules, classes, methods, functions, tracebacks, frame objects, and code objects.
该模块针对模块、类、方法及函数等对象提供了若干有用功能。
getargspec(func)
该方法返回一个命名元组ArgSpect(args, varargs, keywords, defaults)。其中,args为函数位置参数名的列表,varargs表示*参数的名称,keywords表示**参数的名称,defaults则是默认参数值的元组。
在通过__init__参数自动初始化实例属性的实践中,可以通过字节码对象的co_varnames属性来获取函数的位置参数名:
def attr_from_locals(locals_dict):
self = locals_dict.pop('self')
code = self.__init__.__func__.__code__
args = code.co_varnames[1:code.co_argcount]
for k in args:
setattr(self, k, locals_dict[k])
class Foo(object):
def __init__(self, name, color, num=1):
x = 1
attr_from_locals(locals())
然而,当__init__方法使用**特殊参数来接收任意数量的关键字参数时,上述代码将不再适用。可行的解决方案是利用字节码的co_flags属性来判断**参数是否存在。
当函数使用*args语法接受任意数量的位置参数时,co_flags的第2位(0x04)会被置位;使用**kwargs语法时,第3位(0x08)会被置位;若函数为生成器,则第13位(0x2000)会被置位,其余位保留:
>>> def foo(x, *args, **kwargv):
pass
>>> foo.__code__.co_varnames
('x', 'args', 'kwargv')
>>> foo.__code__.co_flags & 0x04
4
>>> foo.__code__.co_flags & 0x08
8
inspect模块的getargspec()方法正是利用此机制来判断并获取函数的特殊参数。现在可以方便地获取__init__中的**参数了:
import inspect
def attr_from_locals(locals_dict):
self = locals_dict.pop('self')
args = inspect.getargspec(self.__init__.__func__).args[1:]
for k in args:
setattr(self, k, locals_dict[k])
keywords = inspect.getargspec(self.__init__.__func__).keywords
if keywords:
keywords_dict = locals_dict[keywords]
for k in keywords_dict:
setattr(self, k, keywords_dict[k])
class Foo(object):
def __init__(self, name, **kwargv):
attr_from_locals(locals())
f = Foo('bar', color='yellow', num=1)
print f.__dict__
运行结果为:
{'color': 'yellow', 'num': 1, 'name': 'bar'}
对象已正确初始化。
getmembers(object[, predicate])
该方法返回一个包含对象所有成员(name, value)的列表。其返回内容比对象的__dict__包含的内容更多,源码实现是通过dir()函数完成的。
predicate是一个可选的函数参数,只有被此函数判断为True的成员才会被返回。
getmodule(object)
返回定义该对象的模块。
getsource(object)
返回对象的源代码字符串。
getsourcelines(object)
返回一个元组,元组的第一个元素为对象源代码行的列表,第二个元素为首行源代码的行号。
ismodule, isclass, ismethod, isfunction, isbuiltin
这是一系列用于判断对象类型的方法,大多是对isinstance(object, types.FunctionType)等语句的封装函数。
现在可以利用类型判断来返回一个类的方法列表:
class Foo(object): '''Foo doc''' def __init__(self, name): self.__name = name def getname(self): return self.__name inspect.getmembers(Foo, inspect.ismethod)
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









