首页 > 学院 > 开发设计 > 正文

Python函数信息

2019-11-14 17:17:28
字体:
来源:转载
供稿:网友

Python函数func的信息可以通过func.func_*和func.func_code来获取

一、先看看它们的应用吧:

1.获取原函数名称:

1 >>> def yes():pass2 3 >>> a=yes4 >>> a.func_name5 'yes'6 >>> 

2.获取函数的flags【后面有用,先说这个】

[python docs]:The following flag bits are defined for co_flags: bit 0x04 is set if the function uses the *arguments syntax to accept an arbitrary number of positional arguments; bit 0x08 is set if the function uses the **keyWords syntax to accept arbitrary keyword arguments; bit 0x20 is set if the function is a generator.

由这段Python官方文档可知,函数的flags与参数的定义方式有关,看看下面的试验:

>>> def yes():pass>>> yes.func_code.co_flags67>>> def yes(a):pass>>> yes.func_code.co_flags67>>> def yes(a,b=3):pass>>> yes.func_code.co_flags67>>> def yes(*args):pass>>> yes.func_code.co_flags71>>> def yes(a,*args):pass>>> yes.func_code.co_flags71>>> def yes(a,b=32,*args):pass>>> yes.func_code.co_flags71>>> def yes(*args,**kw):pass>>> yes.func_code.co_flags79>>> def yes(a,*args,**kw):pass>>> yes.func_code.co_flags79>>> def yes(a,b=3,*args,**kw):pass>>> yes.func_code.co_flags79>>> def yes(**kw):pass>>> yes.func_code.co_flags75>>> def yes(a,**kw):pass>>> yes.func_code.co_flags75>>> def yes(a,b=1,**kw):pass>>> yes.func_code.co_flags75>>>>>> yes=(x for x in range(100))>>> yes<generator object <genexPR> at 0x0000000002FF22D0>>>> [x for x in dir(yes) if not 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_flags99>>> 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 = 1yes.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 = 1yes.gi_code.co_flags = 99yes.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 = 2yes.gi_code.co_stacksize = 2yes.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):pass2 SyntaxError: 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_argcount is the number of positional arguments (including arguments with default values);

int=>func函数的位置参数的个数,实际上python函数定义时定义的前面不加星号的所有参数都是位置参数,我们所说的关键字参数只是调用时候的说法。
2.func.func_code.co_cellvars:co_cellvars is a tuple containing the names of local variables that are referenced by nested functions;

tuple=>func函数中所有被其嵌套函数引用了的func函数的局部变量
3.func.func_code.co_code:co_code is a string representing the sequence of bytecode instructions;

str=>func函数的编译后的字节码
4.func.func_code.co_consts:co_consts is a tuple containing the literals used by the bytecode;

tuple=>func函数中的所有常量,如0,True,'',None
5.func.func_code.co_filename:co_filename is the filename from which the code was compiled;

str=>func函数的定义所在的源文件路径
6.func.func_code.co_firstlineno:co_firstlineno is the first line number of the function;

int=>func函数的定义在其源文件中的第一行的行号
7.func.func_code.co_flags:co_flags is an integer encoding a number of flags for the interpreter;

int=>func函数参数传递方式的编码,比如*args,**kw等形式
8.func.func_code.co_freevars:co_freevars is a tuple containing the names of free variables;

tuple=>func函数中所有的自由变量的名称
9.func.func_code.co_lnotab:co_lnotab is 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_name gives the function name;

str=>func函数的名称
11.func.func_code.co_names:co_names is a tuple containing the names used by the bytecode;

tuple=>func函数中所有的被字节码使用到的名称,比如模块名,方法名等
12.func.func_code.co_nlocals:co_nlocals is the number of local variables used by the function (including arguments);

int=>func函数用到的局部变量的数目(包括参数)
13.func.func_code.co_stacksize:co_stacksize is the required stack size (including local variables);

func函数所需的堆栈大小(包括所有局部变量)
14.func.func_code.co_varnames:co_varnames is a tuple containing the names of the local variables (starting with the argument names);

tuple=>func函数中所有使用到的local variables的名称,参数按顺序排在最前面,其它的按在代码中出现的顺序排列;

四、看下面的一个实验:

 1 #coding=utf-8 2 import os,sys 3  4 def decorator(printResult=False): 5     def _decorator(func): 6         name=func.func_name 7         print '%s() was post to _decorator()'%name 8         def __decorator(*args,**kw): 9             print 'Call the function %s() in __decorator().'%/10                   func.func_name11             if printResult:12                 print func(*args,**kw),'#print in __decorator().'13             else:14                 return func(*args,**kw)15         return __decorator16     return _decorator17 18 def GetRandName(length,isVar=False):19     u'''Get random name with string.letters+'_'+string.digits20 21     length=>The length of name.22     isVar=>The name must be a varname.23     '''24     varName,chars=[],string.letters+'_'+string.digits25     if isVar:26         varName.append(chars[:53][random.randint(0,52)])27         length-=128     for i in range(length):29         varName.append(chars[random.randint(0,62)])30     varName=''.join(varName)31     return varName32 33 def func_info(func):34     print '%s() information:'%func.func_name35     for name in [x for x in dir(func) if x.startswith('func_')]:36         print '%s.%s = %r'%(func.func_name,name,37             eval('%s.%s'%(func.func_name,name)))38     for name in [x for x in dir(func.func_code) if x.startswith('co_')]:39         print '%s.func_code.%s = %r'%(func.func_name,name,40             eval('%s.func_code.%s'%(func.func_name,name)))41 #输出GetRandName()函数的信息42 func_info(GetRandName)43 print '-'*8044 #输出decorator()函数的信息45 func_info(decorator)46 print '-'*8047 #将GetRandName函数用装饰器先装饰一下48 GetRandName=decorator(True)(GetRandName)49 #装饰后GetRandName变成__decorator()函数50 print 'GetRandName=%r'%GetRandName51 #输出此时的GetRandName即__decorator()函数的信息52 print '%s() information:'%GetRandName.func_name53 for name in [x for x in dir(GetRandName) if x.startswith('func_')]:54     print '%s.%s = %r'%(GetRandName.func_name,name,55         eval('GetRandName.%s'%name))56 for name in [x for x in dir(GetRandName.func_code) if x.startswith('co_')]:57     print '%s.func_code.%s = %r'%(GetRandName.func_name,name,58         eval('GetRandName.func_code.%s'%name))

运行结果:

 1 Python 2.7.8 (default, Jun 30 2014, 16:08:48) [MSC v.1500 64 bit (AMD64)] on win32 2 Type "copyright", "credits" or "license()" for more information. 3 >>> ================================ RESTART ================================ 4 >>>  5 GetRandName() information: 6 GetRandName.func_closure = None 7 GetRandName.func_code = <code object GetRandName at 0000000002107F30, file "E:/文档/程序库/Python程序/func_information.py", line 18> 8 GetRandName.func_defaults = (False,) 9 GetRandName.func_dict = {}10 GetRandName.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    "11 GetRandName.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>}12 GetRandName.func_name = 'GetRandName'13 GetRandName.func_code.co_argcount = 214 GetRandName.func_code.co_cellvars = ()15 GetRandName.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'16 GetRandName.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, '')17 GetRandName.func_code.co_filename = 'E:///xce/xc4/xb5/xb5///xb3/xcc/xd0/xf2/xbf/xe2//Python/xb3/xcc/xd0/xf2//func_information.py'18 GetRandName.func_code.co_firstlineno = 1819 GetRandName.func_code.co_flags = 6720 GetRandName.func_code.co_freevars = ()21 GetRandName.func_code.co_lnotab = '/x00/x06/x1b/x01/x06/x01!/x01/r/x01/x13/x01!/x01/x0f/x01'22 GetRandName.func_code.co_name = 'GetRandName'23 GetRandName.func_code.co_names = ('string', 'letters', 'digits', 'append', 'random', 'randint', 'range', 'join')24 GetRandName.func_code.co_nlocals = 525 GetRandName.func_code.co_stacksize = 626 GetRandName.func_code.co_varnames = ('length', 'isVar', 'varName', 'chars', 'i')27 --------------------------------------------------------------------------------28 decorator() information:29 decorator.func_closure = None30 decorator.func_code = <code object decorator at 0000000002107AB0, file "E:/文档/程序库/Python程序/func_information.py", line 4>31 decorator.func_defaults = (False,)32 decorator.func_dict = {}33 decorator.func_doc = None34 decorator.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>}35 decorator.func_name = 'decorator'36 decorator.func_code.co_argcount = 137 decorator.func_code.co_cellvars = ('printResult',)38 decorator.func_code.co_code = '/x87/x00/x00f/x01/x00d/x01/x00/x86/x00/x00}/x01/x00|/x01/x00S'39 decorator.func_code.co_consts = (None, <code object _decorator at 0000000002107830, file "E:/文档/程序库/Python程序/func_information.py", line 5>)40 decorator.func_code.co_filename = 'E:///xce/xc4/xb5/xb5///xb3/xcc/xd0/xf2/xbf/xe2//Python/xb3/xcc/xd0/xf2//func_information.py'41 decorator.func_code.co_firstlineno = 442 decorator.func_code.co_flags = 343 decorator.func_code.co_freevars = ()44 decorator.func_code.co_lnotab = '/x00/x01/x0f/x0b'45 decorator.func_code.co_name = 'decorator'46 decorator.func_code.co_names = ()47 decorator.func_code.co_nlocals = 248 decorator.func_code.co_stacksize = 249 decorator.func_code.co_varnames = ('printResult', '_decorator')50 --------------------------------------------------------------------------------51 GetRandName() was post to _decorator()52 GetRandName=<function __decorator at 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 __decorator at 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 __decorator at 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 >>> 

 


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表