python找对象函数 python查询对象类型( 五 )


2.8. 代码块(code)
代码块可以由类源代码、函数源代码或是一个简单的语句代码编译得到 。这里我们只考虑它指代一个函数时的情况;2.5节中我们曾提到可以使用函数的func_code属性获取到它 。code的属性全部是只读的 。
co_argcount: 普通参数的总数 , 不包括*参数和**参数 。
co_names: 所有的参数名(包括*参数和**参数)和局部变量名的元组 。
co_varnames: 所有的局部变量名的元组 。
co_filename: 源代码所在的文件名 。
co_flags:这是一个数值,每一个二进制位都包含了特定信息 。较关注的是0b100(0×4)和0b1000(0×8),如果co_flags0b100 != 0 , 说明使用了*args参数;如果co_flags0b1000 != 0,说明使用了**kwargs参数 。另外,如果co_flags0b100000(0×20) != 0 , 则说明这是一个生成器函数(generator function) 。
co = cat.sayHi.func_code
print co.co_argcount # 1
print co.co_names # ('name',)
print co.co_varnames # ('self',)
print co.co_flags0b100 # 0
2.9. 栈帧(frame)
栈帧表示程序运行时函数调用栈中的某一帧 。函数没有属性可以获取它,因为它在函数调用时才会产生,而生成器则是由函数调用返回的,所以有属性指向栈帧 。想要获得某个函数相关的栈?。?则必须在调用这个函数且这个函数尚未返回时获取 。你可以使用sys模块的_getframe()函数、或inspect模块的currentframe()函数获取当前栈帧 。这里列出来的属性全部是只读的 。
f_back: 调用栈的前一帧 。
f_code: 栈帧对应的code对象 。
f_locals: 用在当前栈帧时与内建函数locals()相同,但你可以先获取其他帧然后使用这个属性获取那个帧的locals() 。
f_globals: 用在当前栈帧时与内建函数globals()相同,但你可以先获取其他帧…… 。
def add(x, y=1):
f = inspect.currentframe()
print f.f_locals # same as locals()
print f.f_back # frame object at 0x...
return x+y
add(2)
2.10. 追踪(traceback)
追踪是在出现异常时用于回溯的对象,与栈帧相反 。由于异常时才会构建,而异常未捕获时会一直向外层栈帧抛出 , 所以需要使用try才能见到这个对象 。你可以使用sys模块的exc_info()函数获得它,这个函数返回一个元组 , 元素分别是异常类型、异常对象、追踪 。traceback的属性全部是只读的 。
tb_next: 追踪的下一个追踪对象 。
tb_frame: 当前追踪对应的栈帧 。
tb_lineno: 当前追踪的行号 。
def div(x, y):
try:
return x/y
except:
tb = sys.exc_info()[2] # return (exc_type, exc_value, traceback)
print tb
print tb.tb_lineno # "return x/y" 的行号
div(1, 0)
3. 使用inspect模块
inspect模块提供了一系列函数用于帮助使用自省 。下面仅列出较常用的一些函数,想获得全部的函数资料可以查看inspect模块的文档 。
3.1. 检查对象类型
is{module|class|function|method|builtin}(obj):
检查对象是否为模块、类、函数、方法、内建函数或方法 。
isroutine(obj):
用于检查对象是否为函数、方法、内建函数或方法等等可调用类型 。用这个方法会比多个is*()更方便,不过它的实现仍然是用了多个is*() 。
im = cat.sayHi
if inspect.isroutine(im):
im()
对于实现了__call__的类实例 , 这个方法会返回False 。如果目的是只要可以直接调用就需要是True的话,不妨使用isinstance(obj, collections.Callable)这种形式 。我也不知道为什么Callable会在collections模块中,抱歉!我猜大概是因为collections模块中包含了很多其他的ABC(Abstract Base Class)的缘故吧:)
3.2. 获取对象信息

推荐阅读