设为首页 收藏本站
查看: 674|回复: 0

[经验分享] Python函数信息

[复制链接]

尚未签到

发表于 2015-11-30 08:23:04 | 显示全部楼层 |阅读模式
  Python函数func的信息可以通过func.func_*和func.func_code来获取
  一、先看看它们的应用吧:
  1.获取原函数名称:



1 >>> def yes():pass
2
3 >>> a=yes
4 >>> a.func_name
5 '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_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=(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_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):pass
2 SyntaxError: invalid syntax
3 >>>
  故如此。到此,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_name
11             if printResult:
12                 print func(*args,**kw),'#print in __decorator().'
13             else:
14                 return func(*args,**kw)
15         return __decorator
16     return _decorator
17
18 def GetRandName(length,isVar=False):
19     u'''Get random name with string.letters+'_'+string.digits
20
21     length=>The length of name.
22     isVar=>The name must be a varname.
23     '''
24     varName,chars=[],string.letters+'_'+string.digits
25     if isVar:
26         varName.append(chars[:53][random.randint(0,52)])
27         length-=1
28     for i in range(length):
29         varName.append(chars[random.randint(0,62)])
30     varName=''.join(varName)
31     return varName
32
33 def func_info(func):
34     print '%s() information:'%func.func_name
35     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 '-'*80
44 #输出decorator()函数的信息
45 func_info(decorator)
46 print '-'*80
47 #将GetRandName函数用装饰器先装饰一下
48 GetRandName=decorator(True)(GetRandName)
49 #装饰后GetRandName变成__decorator()函数
50 print 'GetRandName=%r'%GetRandName
51 #输出此时的GetRandName即__decorator()函数的信息
52 print '%s() information:'%GetRandName.func_name
53 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 = 2
14 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 = 18
19 GetRandName.func_code.co_flags = 67
20 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 = 5
25 GetRandName.func_code.co_stacksize = 6
26 GetRandName.func_code.co_varnames = ('length', 'isVar', 'varName', 'chars', 'i')
27 --------------------------------------------------------------------------------
28 decorator() information:
29 decorator.func_closure = None
30 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 = None
34 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 = 1
37 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 = 4
42 decorator.func_code.co_flags = 3
43 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 = 2
48 decorator.func_code.co_stacksize = 2
49 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 = None
57 __decorator.func_dict = {}
58 __decorator.func_doc = None
59 __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 = 0
62 __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 = 8
67 __decorator.func_code.co_flags = 31
68 __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 = 2
73 __decorator.func_code.co_stacksize = 3
74 __decorator.func_code.co_varnames = ('args', 'kw')
75 >>>
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-145104-1-1.html 上篇帖子: 初学python,感受和C的不同 下篇帖子: 合并百度影音的离线数据 with python 2.3 格式更新
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表