Python函数func的信息可以通过func.func_*和func.func_code来获取
一、先看看它们的应用吧:
1.获取原函数名称:
1 >>>def yes():pass23 >>> a=yes4 >>>a.func_name5'yes'6 >>>
2.获取函数的flags【后面有用,先说这个】
[python docs]:The following flag bits are defined forco_flags: bit0x04is set if the function uses the*argumentssyntax to accept an arbitrary number of positional arguments; bit0x08is set if the function uses the**keyWordssyntax to accept arbitrary keyword arguments; bit0x20is set if the function is a generator.
由这段Python官方文档可知,函数的flags与参数的定义方式有关,看看下面的试验:
>>>def yes():pass
>>>yes.func_code.co_flags
67
>>>def yes(a):pass
>>>yes.func_code.co_flags
67
>>>def yes(a,b=3):pass
>>>yes.func_code.co_flags
67
>>>def yes(*args):pass
>>>yes.func_code.co_flags
71
>>>def yes(a,*args):pass
>>>yes.func_code.co_flags
71
>>>def yes(a,b=32,*args):pass
>>>yes.func_code.co_flags
71
>>>def yes(*args,**kw):pass
>>>yes.func_code.co_flags
79
>>>def yes(a,*args,**kw):pass
>>>yes.func_code.co_flags
79
>>>def yes(a,b=3,*args,**kw):pass
>>>yes.func_code.co_flags
79
>>>def yes(**kw):pass
>>>yes.func_code.co_flags
75
>>>def yes(a,**kw):pass
>>>yes.func_code.co_flags
75
>>>def yes(a,b=1,**kw):pass
>>>yes.func_code.co_flags
75
>>>
>>> yes=(xfor xin range(100))
>>>yes
<generator object <genexPR> at 0x0000000002FF22D0>
>>> [xfor xin dir(yes)ifnot x.startswith('_')]
['close','gi_code','gi_frame','gi_running','next','send','throw']
>>>dir(yes)
['__class__','__delattr__','__doc__','__format__','__getattribute__','__hash__','__init__','__iter__','__name__','__new__','__reduce__','__reduce_ex__','__repr__','__setattr__','__sizeof__','__str__','__subclasshook__','close','gi_code','gi_frame','gi_running','next','send','throw']
>>>dir(yes.gi_code)
['__class__','__cmp__','__delattr__','__doc__','__eq__','__format__','__ge__','__getattribute__','__gt__','__hash__','__init__','__le__','__lt__','__ne__','__new__','__reduce__','__reduce_ex__','__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'co_argcount', 'co_cellvars', 'co_code', 'co_consts', 'co_filename', 'co_firstlineno', 'co_flags', 'co_freevars', 'co_lnotab', 'co_name', 'co_names', 'co_nlocals', 'co_stacksize', 'co_varnames']
>>> [x for x in dir(yes.gi_code) if x.startswith('co_')]
['co_argcount', 'co_cellvars', 'co_code', 'co_consts', 'co_filename', 'co_firstlineno', 'co_flags', 'co_freevars', 'co_lnotab', 'co_name', 'co_names', 'co_nlocals', 'co_stacksize', 'co_varnames']
>>> yes.gi_code.co_flags
99
>>> yes.next()
0
>>> yes.next()
1
>>> yes.gi_code.co_varnames
('.0', 'x')
>>> for name in [x for x in dir(yes.gi_code) if x.startswith('co_')]:
print 'yes.gi_code.%s = %r'%(name,eval('yes.gi_code.%s'%name))
yes.gi_code.co_argcount = 1
yes.gi_code.co_cellvars = ()
yes.gi_code.co_code = '|\x00\x00]\x0b\x00}\x01\x00|\x01\x00V\x01q\x03\x00d\x00\x00S'
yes.gi_code.co_consts = (None,)
yes.gi_code.co_filename = '<pyshell#46>'
yes.gi_code.co_firstlineno = 1
yes.gi_code.co_flags = 99
yes.gi_code.co_freevars = ()
yes.gi_code.co_lnotab = '\x06\x00'
yes.gi_code.co_name = '<genexpr>'
yes.gi_code.co_names = ()
yes.gi_code.co_nlocals = 2
yes.gi_code.co_stacksize = 2
yes.gi_code.co_varnames = ('.0', 'x')
>>>
【1】function没有*args或**kw时,func.func_code.co_flags=67;
【2】function有*args没有**kw时,func.func_code.co_flags=71;
【3】function没有*args有**kw时,func.func_code.co_flags=75;
【4】function既有*args也有**kw时,func.func_code.co_flags=79;
【5】function是一个generator时,func.gi_code.co_flags=99.
3.获取func函数的所有位置参数的个数:
func.func_code.co_argcount
4.获取func函数签名:
[1]callable(func),True=>function,False=>generator
[2]func的定义的所有位置参数变量名:pVars=func.func_code.co_varnames[:func.func_code.co_argcount]
[3]func的默认参数及默认值:func.func_defaults
[4]func的所有带默认值的参数的参数名:dVars=pVars[-len(func.func_defaults):]【当然首先要判断func.func_defaults=?=None】
[5]根据func.func_code.co_flags来判断有无带星号的参数,按照上面的判定规则:
a.如果func.func_code.co_flags==67,无带星号的参数;
b.如果func.func_code.co_flags==71,只有带一个星号的参数,它的参数名是func.func_code.co_varnames[func.func_code.co_argcount]
c.如果func.func_code.co_flags==75,只有带两个星号的参数,它的参数名是func.func_code.co_varnames[func.func_code.co_argcount]
d. 如果func.func_code.co_flags==79,有两个带星号的参数,它们的参数名是 func.func_code.co_varnames[func.func_code.co_argcount:func.func_code.co_argcount+2], 其中第一个是带一个星号的,第二个是带两个星号的
因为:
1 >>>def yes(**kw,*args):pass2SyntaxError: invalid syntax3 >>>
故如此。到此,func函数的函数签名就可以被还原了。
二、func.func_*
1.func.func_closure:
2.func.func_code:详见下面第三条
3.func.func_defaults:tuple=>func函数的参数中的所有默认值
4.func.func_dict
5.func.func_doc:str=>func函数的文档字符串
6.func.func_globals:dict=>func函数的全局环境
7.func.func_name:str=>func函数的函数名
三、func.func_code【翻译有不周之处请指正】
1.func.func_code.co_argcount:co_argcountis the number of positional arguments (including arguments with default values);
int=>func函数的位置参数的个数,实际上python函数定义时定义的前面不加星号的所有参数都是位置参数,我们所说的关键字参数只是调用时候的说法。
2.func.func_code.co_cellvars:co_cellvarsis a tuple containing the names of local variables that are referenced by nested functions;
tuple=>func函数中所有被其嵌套函数引用了的func函数的局部变量
3.func.func_code.co_code:co_codeis a string representing the sequence of bytecode instructions;
str=>func函数的编译后的字节码
4.func.func_code.co_consts:co_constsis a tuple containing the literals used by the bytecode;
tuple=>func函数中的所有常量,如0,True,'',None
5.func.func_code.co_filename:co_filenameis the filename from which the code was compiled;
str=>func函数的定义所在的源文件路径
6.func.func_code.co_firstlineno:co_firstlinenois the first line number of the function;
int=>func函数的定义在其源文件中的第一行的行号
7.func.func_code.co_flags:co_flagsis an integer encoding a number of flags for the interpreter;
int=>func函数参数传递方式的编码,比如*args,**kw等形式
8.func.func_code.co_freevars:co_freevarsis a tuple containing the names of free variables;
tuple=>func函数中所有的自由变量的名称
9.func.func_code.co_lnotab:co_lnotabis a string encoding the mapping from bytecode offsets to line numbers (for details see the source code of the interpreter);
10.func.func_code.co_name:co_namegives the function name;
str=>func函数的名称
11.func.func_code.co_names:co_namesis a tuple containing the names used by the bytecode;
tuple=>func函数中所有的被字节码使用到的名称,比如模块名,方法名等
12.func.func_code.co_nlocals:co_nlocalsis the number of local variables used by the function (including arguments);
int=>func函数用到的局部变量的数目(包括参数)
13.func.func_code.co_stacksize:co_stacksizeis the required stack size (including local variables);
func函数所需的堆栈大小(包括所有局部变量)
14.func.func_code.co_varnames:co_varnamesis a tuple containing the names of the local variables (starting with the argument names);
tuple=>func函数中所有使用到的local variables的名称,参数按顺序排在最前面,其它的按在代码中出现的顺序排列;
四、看下面的一个实验:
1#coding=utf-82importos,sys34defdecorator(printResult=False):5def_decorator(func):6name=func.func_name7print'%s() was post to _decorator()'%name8def__decorator(*args,**kw):9print'Call the function %s() in __decorator().'%\10func.func_name11ifprintResult:12printfunc(*args,**kw),'#print in __decorator().'13else:14returnfunc(*args,**kw)15return__decorator16return_decorator1718defGetRandName(length,isVar=False):19u'''Get random name with string.letters+'_'+string.digits2021length=>The length of name.22isVar=>The name must be a varname.23'''24varName,chars=[],string.letters+'_'+string.digits25ifisVar:26varName.append(chars[:53][random.randint(0,52)])27length-=128foriinrange(length):29varName.append(chars[random.randint(0,62)])30varName=''.join(varName)31returnvarName3233deffunc_info(func):34print'%s() information:'%func.func_name35fornamein[xforxindir(func)ifx.startswith('func_')]:36print'%s.%s = %r'%(func.func_name,name,37eval('%s.%s'%(func.func_name,name)))38fornamein[xforxindir(func.func_code)ifx.startswith('co_')]:39print'%s.func_code.%s = %r'%(func.func_name,name,40eval('%s.func_code.%s'%(func.func_name,name)))41#输出GetRandName()函数的信息42func_info(GetRandName)43print'-'*8044#输出decorator()函数的信息45func_info(decorator)46print'-'*8047#将GetRandName函数用装饰器先装饰一下48GetRandName=decorator(True)(GetRandName)49#装饰后GetRandName变成__decorator()函数50print'GetRandName=%r'%GetRandName51#输出此时的GetRandName即__decorator()函数的信息52print'%s() information:'%GetRandName.func_name53fornamein[xforxindir(GetRandName)ifx.startswith('func_')]:54print'%s.%s = %r'%(GetRandName.func_name,name,55eval('GetRandName.%s'%name))56fornamein[xforxindir(GetRandName.func_code)ifx.startswith('co_')]:57print'%s.func_code.%s = %r'%(GetRandName.func_name,name,58eval('GetRandName.func_code.%s'%name))
运行结果:
1Python 2.7.8 (default, Jun 30 2014, 16:08:48) [MSC v.1500 64bit (AMD64)] on win322Type"copyright","credits"or"license()"formore information.3>>> ================================ RESTART ================================4>>>5GetRandName() information:6GetRandName.func_closure =None7GetRandName.func_code = <code object GetRandName at 0000000002107F30, file"E:\文档\程序库\Python程序\func_information.py", line 18>8GetRandName.func_defaults =(False,)9GetRandName.func_dict ={}10GetRandName.func_doc = u"Get random name with string.letters+'_'+string.digits\n\n length=>The length of name.\n isVar=>The name must be a varname.\n"11GetRandName.func_globals = {'__builtins__': <module'__builtin__'(built-in)>,'__file__':'E:\\\xce\xc4\xb5\xb5\\\xb3\xcc\xd0\xf2\xbf\xe2\\Python\xb3\xcc\xd0\xf2\\func_information.py','func_info': <function func_info at 0x0000000002BDD3C8>,'__package__': None,'sys': <module'sys'(built-in)>,'__name__':'__main__','GetRandName': <function GetRandName at 0x0000000002BE0D68>,'os': <module'os'from'D:\Python27\lib\os.pyc'>,'__doc__': None,'decorator': <function decorator at 0x00000000021199E8>}12GetRandName.func_name ='GetRandName'13GetRandName.func_code.co_argcount = 214GetRandName.func_code.co_cellvars =()15GetRandName.func_code.co_code ='g\x00\x00t\x00\x00j\x01\x00d\x01\x00\x17t\x00\x00j\x02\x00\x17\x02}\x02\x00}\x03\x00|\x01\x00rO\x00|\x02\x00j\x03\x00|\x03\x00d\x02\x00 t\x04\x00j\x05\x00d\x03\x00d\x04\x00\x83\x02\x00\x19\x83\x01\x00\x01|\x00\x00d\x05\x008}\x00\x00n\x00\x00x1\x00t\x06\x00|\x00\x00\x83\x01\x00D]#\x00}\x04\x00|\x02\x00j\x03\x00|\x03\x00t\x04\x00j\x05\x00d\x03\x00d\x06\x00\x83\x02\x00\x19\x83\x01\x00\x01q\\\x00Wd\x07\x00j\x07\x00|\x02\x00\x83\x01\x00}\x02\x00|\x02\x00S'16GetRandName.func_code.co_consts = (u"Get random name with string.letters+'_'+string.digits\n\n length=>The length of name.\n isVar=>The name must be a varname.\n",'_', 53, 0, 52, 1, 62,'')17GetRandName.func_code.co_filename ='E:\\\xce\xc4\xb5\xb5\\\xb3\xcc\xd0\xf2\xbf\xe2\\Python\xb3\xcc\xd0\xf2\\func_information.py'18GetRandName.func_code.co_firstlineno = 1819GetRandName.func_code.co_flags = 6720GetRandName.func_code.co_freevars =()21GetRandName.func_code.co_lnotab ='\x00\x06\x1b\x01\x06\x01!\x01\r\x01\x13\x01!\x01\x0f\x01'22GetRandName.func_code.co_name ='GetRandName'23GetRandName.func_code.co_names = ('string','letters','digits','append','random','randint','range','join')24GetRandName.func_code.co_nlocals = 525GetRandName.func_code.co_stacksize = 626GetRandName.func_code.co_varnames = ('length','isVar','varName','chars','i')27--------------------------------------------------------------------------------28decorator() information:29decorator.func_closure =None30decorator.func_code = <code object decorator at 0000000002107AB0, file"E:\文档\程序库\Python程序\func_information.py", line 4>31decorator.func_defaults =(False,)32decorator.func_dict ={}33decorator.func_doc =None34decorator.func_globals = {'__builtins__': <module'__builtin__'(built-in)>,'__file__':'E:\\\xce\xc4\xb5\xb5\\\xb3\xcc\xd0\xf2\xbf\xe2\\Python\xb3\xcc\xd0\xf2\\func_information.py','func_info': <function func_info at 0x0000000002BDD3C8>,'__package__': None,'sys': <module'sys'(built-in)>,'__name__':'__main__','GetRandName': <function GetRandName at 0x0000000002BE0D68>,'os': <module'os'from'D:\Python27\lib\os.pyc'>,'__doc__': None,'decorator': <function decorator at 0x00000000021199E8>}35decorator.func_name ='decorator'36decorator.func_code.co_argcount = 137decorator.func_code.co_cellvars = ('printResult',)38decorator.func_code.co_code ='\x87\x00\x00f\x01\x00d\x01\x00\x86\x00\x00}\x01\x00|\x01\x00S'39decorator.func_code.co_consts = (None, <code object _decorator at 0000000002107830, file"E:\文档\程序库\Python程序\func_information.py", line 5>)40decorator.func_code.co_filename ='E:\\\xce\xc4\xb5\xb5\\\xb3\xcc\xd0\xf2\xbf\xe2\\Python\xb3\xcc\xd0\xf2\\func_information.py'41decorator.func_code.co_firstlineno = 442decorator.func_code.co_flags = 343decorator.func_code.co_freevars =()44decorator.func_code.co_lnotab ='\x00\x01\x0f\x0b'45decorator.func_code.co_name ='decorator'46decorator.func_code.co_names =()47decorator.func_code.co_nlocals = 248decorator.func_code.co_stacksize = 249decorator.func_code.co_varnames = ('printResult','_decorator')50--------------------------------------------------------------------------------51GetRandName() was post to _decorator()52GetRandName=<function__decoratorat 0x0000000002BDD4A8>53__decorator() information:54__decorator.func_closure = (<cell at 0x0000000002BF18E8: function object at 0x0000000002BE0D68>, <cell at 0x0000000002BF1828: bool object at 0x000000001E284280>)55__decorator.func_code = <code object__decoratorat 0000000002124030, file"E:\文档\程序库\Python程序\func_information.py", line 8>56__decorator.func_defaults =None57__decorator.func_dict ={}58__decorator.func_doc =None59__decorator.func_globals = {'name':'func_globals','__builtins__': <module'__builtin__'(built-in)>,'__file__':'E:\\\xce\xc4\xb5\xb5\\\xb3\xcc\xd0\xf2\xbf\xe2\\Python\xb3\xcc\xd0\xf2\\func_information.py','func_info': <function func_info at 0x0000000002BDD3C8>,'__package__': None,'sys': <module'sys'(built-in)>,'x':'func_name','__name__':'__main__','GetRandName': <function__decoratorat 0x0000000002BDD4A8>,'os': <module'os'from'D:\Python27\lib\os.pyc'>,'__doc__': None,'decorator': <function decorator at 0x00000000021199E8>}60__decorator.func_name ='__decorator'61__decorator.func_code.co_argcount =062__decorator.func_code.co_cellvars =()63__decorator.func_code.co_code ="d\x01\x00\x88\x00\x00j\x00\x00\x16GH\x88\x01\x00r'\x00\x88\x00\x00|\x00\x00|\x01\x00\x8e\x00\x00Gd\x02\x00GHn\r\x00\x88\x00\x00|\x00\x00|\x01\x00\x8e\x00\x00Sd\x00\x00S"64__decorator.func_code.co_consts = (None,'Call the function %s() in __decorator().','#print in __decorator().')65__decorator.func_code.co_filename ='E:\\\xce\xc4\xb5\xb5\\\xb3\xcc\xd0\xf2\xbf\xe2\\Python\xb3\xcc\xd0\xf2\\func_information.py'66__decorator.func_code.co_firstlineno = 867__decorator.func_code.co_flags = 3168__decorator.func_code.co_freevars = ('func','printResult')69__decorator.func_code.co_lnotab ='\x00\x01\x03\x01\t\x01\x06\x01\x15\x02'70__decorator.func_code.co_name ='__decorator'71__decorator.func_code.co_names = ('func_name',)72__decorator.func_code.co_nlocals = 273__decorator.func_code.co_stacksize = 374__decorator.func_code.co_varnames = ('args','kw')75>>>