Python语法学习记录(24):inspect模块介绍及常用使用方式

1、简述

获取函数签名对象。

函数签名包含了一个函数的信息,包括函数名、它的参数类型、它所在的类和名称空间及其他信息)。

2、基本用法

inspect模块主要提供了四种用处:

1.对是否是模块、框架、函数进行类型检查
2.获取源码
3.获取类或者函数的参数信息
4.解析堆栈

2.1 对是否是模块、框架、函数进行类型检查

inspect.getmembers

getmembers的实现步骤

获取 object 的所有成员的名字,包含 object 的父类的成员,存入 names 列表
从 object 的基类中获取 DynamicClassAttribute 类型的成员,添加到 names 列表中
遍历 names 列表,通过 getattr 方法获取 object 中所有属性的值,getattr(x, ‘y’) 相当于 x.y
用 predicate 判断成员值,把通过判断的成员,以(成员名, 成员值)的形式添加到 results 这个列表中
对 results 列表按 成员名 进行排序

inspect.getmembers(object[, predicate])

第二个参数通常可以根据需要调用如下16个方法;

返回值为object的所有成员,以(name,value)对组成的列表

inspect.ismodule(object): 是否为模块
inspect.isclass(object):是否为类
inspect.ismethod(object):是否为方法(bound method written in python)
inspect.isfunction(object):是否为函数(python function, including lambda expression)
inspect.isgeneratorfunction(object):是否为python生成器函数
inspect.isgenerator(object):是否为生成器
inspect.istraceback(object): 是否为traceback
inspect.isframe(object):是否为frame
inspect.iscode(object):是否为code
inspect.isbuiltin(object):是否为built-in函数或built-in方法
inspect.isroutine(object):是否为用户自定义或者built-in函数或方法
inspect.isabstract(object):是否为抽象基类
inspect.ismethoddescriptor(object):是否为方法标识符
inspect.isdatadescriptor(object):是否为数字标识符,数字标识符有__get__ 和__set__属性; 通常也有__name__和__doc__属性
inspect.isgetsetdescriptor(object):是否为getset descriptor
inspect.ismemberdescriptor(object):是否为member descriptor

inspect的getmembers()方法可以获取对象(module、class、method等)的如下属性:

AttributeTypeDescriptionNotes
__doc__moduledocumentation string 文档字符串
__file__filename (missing for built-in modules) 文件名(内置模块没有文件名)
__doc__classdocumentation string 文档字符串
__module__name of module in which this class was defined 该类型被定义时所在的模块的名称
__doc__methoddocumentation string 文档字符串
__name__name with which this method was defined 该方法定义时所使用的名称
im_classclass object that asked for this method(1)
im_func or __func__function object containing implementation of method 实现该方法的函数对象
im_self or __self__instance to which this method is bound, or None 该方法被绑定的实例,若没有绑定则为 None
__doc__functiondocumentation string 文档字符串
__name__name with which this function was defined 用于定义此函数的名称
func_codecode object containing compiled function bytecode 包含已编译函数的代码对象
func_defaultstuple of any default values for arguments
func_doc(same as __doc__)
func_globalsglobal namespace in which this function was defined
func_name(same as __name__)
__iter__generatordefined to support iteration over container
closeraises new GeneratorExit exception inside the generator to terminate the iteration
gi_codecode object
gi_frameframe object or possibly None once the generator has been exhausted
gi_runningset to 1 when generator is executing, 0 otherwise
nextreturn the next item from the container
sendresumes the generator and “sends” a value that becomes the result of the current yield-expression
throwused to raise an exception inside the generator
tb_frametracebackframe object at this level 此级别的框架对象
tb_lastiindex of last attempted instruction in bytecode
tb_linenocurrent line number in Python source code
tb_nextnext inner traceback object (called by this level)
f_backframenext outer frame object (this frame’s caller)
f_builtinsbuiltins namespace seen by this frame
f_codecode object being executed in this frame
f_exc_tracebacktraceback if raised in this frame, or None
f_exc_typeexception type if raised in this frame, or None
f_exc_valueexception value if raised in this frame, or None
f_globalsglobal namespace seen by this frame
f_lastiindex of last attempted instruction in bytecode
f_linenocurrent line number in Python source code
f_localslocal namespace seen by this frame
f_restricted0 or 1 if frame is in restricted execution mode
f_tracetracing function for this frame, or None
co_argcountcodenumber of arguments (not including * or ** args)
co_codestring of raw compiled bytecode 原始编译字节码的字符串
co_conststuple of constants used in the bytecode 字节码中使用的常量元组
co_filenamename of file in which this code object was created 创建此代码对象的文件的名称
co_firstlinenonumber of first line in Python source code
co_flagsbitmap: 1=optimized | 2=newlocals | 4=*arg |8=**arg
co_lnotabencoded mapping of line numbers to bytecode indices 编码的行号到字节码索引的映射
co_namename with which this code object was defined 定义此代码对象的名称
co_namestuple of names of local variables 局部变量名称的元组
co_nlocalsnumber of local variables 局部变量的数量
co_stacksizevirtual machine stack space required 需要虚拟机堆栈空间
co_varnamestuple of names of arguments and local variables 参数名和局部变量的元组
__doc__builtindocumentation string 文档字符串
__name__original name of this function or method 此函数或方法的原始名称
__self__instance to which a method is bound, or None

例子:

import inspect
# 待获取签名的函数
def func(x:int, y:str, z:list) -> None:
    '''
    weiwei
    '''
    pass
# return signature类型的对象,值为函数的所有参数
print(inspect.signature(func))
# return orderdict key就是参数名  str类型
print(inspect.signature(func).parameters)
# return module的所有成员的name和obj类型
print(inspect.getmembers(func))
# 返回document
print(inspect.getdoc(func))

print(inspect.isfunction(func))         # 是否是函数 
print(inspect.ismethod(func))           # 是否是类的方法 
print(inspect.isgenerator(func))        # 是否是生成器对象 
print(inspect.isgeneratorfunction(func))# 是否是生成器函数 
print(inspect.isclass(func))            # 是否是类 

2.2 获取源码

inspect.getdoc(object)# 获取object的documentation信息
inspect.getcomments(object)
inspect.getfile(object)# 返回对象的文件名
inspect.getmodule(object)# 返回object所属的模块名
inspect.getsourcefile(object)# 返回object的python源文件名;object不能使built-in的module, class, mothod
inspect.getsourcelines(object)# 返回object的python源文件代码的内容,行号+代码行
inspect.getsource(object)# 以string形式返回object的源代码
inspect.cleandoc(doc)

2.3 获取类或者函数的参数信息

inspect.getclasstree(classes[, unique])
inspect.getargspec(func)
inspect.getargvalues(frame)
inspect.formatargspec(args[, varargs, varkw, defaults, formatarg, formatvarargs, formatvarkw, formatvalue, join])
inspect.formatargvalues(args[, varargs, varkw, locals, formatarg, formatvarargs, formatvarkw, formatvalue, join])
inspect.getmro(cls)#元组形式返回cls类的基类(包括cls类),以method resolution顺序;通常cls类为元素的第一个元素
inspect.getcallargs(func[, *args][, **kwds])#将args和kwds参数到绑定到为func的参数名;对bound方法,也绑定第一个参数(通常为self)到相应的实例;返回字典,对应参数名及其值;

例子:

>>> from inspect import getcallargs
>>> def f(a, b=1, *pos, **named):
...     pass
>>> getcallargs(f, 1, 2, 3)
{'a': 1, 'named': {}, 'b': 2, 'pos': (3,)}
>>> getcallargs(f, a=2, x=4)
{'a': 2, 'named': {'x': 4}, 'b': 1, 'pos': ()}
>>> getcallargs(f)
Traceback (most recent call last):
...
TypeError: f() takes at least 1 argument (0 given)

2.4 解析堆栈

inspect.getframeinfo(frame[, context])
inspect.getouterframes(frame[, context])
inspect.getinnerframes(traceback[, context])
inspect.currentframe()
inspect.stack([context])
inspect.trace([context])

3、使用实例一:获取一些常用监控信息

Parameter对象:保存在元组中,是只读的 ; name,参数的名字 ; annotation,参数的注解,可能没有定义 ;default,参数的缺省值,可能没有定义 ;empty,特殊的类,用来标记default属性或者注释annotation属性的空值 ; kind,实参如何绑定到形参,就是形参的类型

import inspect
# 待获取签名的函数
def func(x:int, y:str, z:list) -> None:
  pass

# 获取签名对象,包括函数名,参数等
sig = inspect.signature(func) 
print(type(sig))
print(sig)
# 获取签名中的参数,返回有序字典
params = sig.parameters 
print(params)
# 通过循环并解构
for k, v in enumerate(params.items()):
  name, param = v
  print(param.annotation, param.kind, param.name)
# 获取签名中的返回值类型
ret = sig.return_annotation
print(ret)

image-20201020103044988

4、使用实例二:修饰器检测示例

检查用户输入是否符合参数注解的要求?

思路:调用时,判断用户输入的实参是否符合要求,用户感觉上还是在调用原函数,对用户输入的数据和声明的类型进行对比,如果不符合,提示用户。

import datetime, time
import inspect
def check_str(func):
    def wrapper(*args, **kwargs):
        obj = inspect.signature(func)
        params = obj.parameters
        for k, v in enumerate(params.items()):
            name, param = v
            for i in args:
                if not isinstance(i, param.annotation):
                    print("{}: {} is not string".format(name, i))
                    raise TypeError
        ret = func(*args, **kwargs)
        return ret
    return wrapper

@check_str
def str_add(str1:str, str2:str):
    new_str = str1 + str2
    print(new_str)
str_add("3", "4")
str_add(3, 4)

5、实例三:常用代码模块

5.1 获取该模块的所有类

import inspect

for name, obj in inspect.getmembers(unittest):
    """获取该模块的所有类"""
    if inspect.isclass(obj):
        print(obj.__name__)

举例:

import inspect

for name, obj in inspect.getmembers(inspect):
 """获取该模块的所有类"""
 if inspect.isclass(obj):
     print(obj.__name__)

5.2 获取某个类中的函数

举例

import inspect

class classtest():
 def __init__(self):
     '''哈哈哈'''
     a = 100
 def add(self):
     '''加法'''
     return self.a + 100

"""下面可以写出带序号的方法"""
driver = []
print(classtest.__init__.__doc__)
for i in inspect.getmembers(classtest):#获取Page类中的所有成员方法,i返回的是一个元祖,第一个元素是方法名,第二个是内存地址
 if inspect.isfunction(i[1]):#判断成员是不是一个函数方法
     driver.append(i[1].__doc__)#是打印他的doc
for i in enumerate(driver):
 print(i)

image-20201020160838364

Last

Python函数参数注释 - 阅读

python标准库中inspect 模块简单介绍_阿常呓语的专栏-CSDN博客

Python Inspect模块 - 知乎

python inspect.getmembers 源码分析

python–inspect模块-阿里云开发者社区

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值