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的名称,参数按顺序排在最前面,其它的按在代码中出现的顺序排列;

四、看下面的一个实验:

 #coding=utf-8
import os,sys def decorator(printResult=False):
def _decorator(func):
name=func.func_name
print '%s() was post to _decorator()'%name
def __decorator(*args,**kw):
print 'Call the function %s() in __decorator().'%\
func.func_name
if printResult:
print func(*args,**kw),'#print in __decorator().'
else:
return func(*args,**kw)
return __decorator
return _decorator def GetRandName(length,isVar=False):
u'''Get random name with string.letters+'_'+string.digits length=>The length of name.
isVar=>The name must be a varname.
'''
varName,chars=[],string.letters+'_'+string.digits
if isVar:
varName.append(chars[:53][random.randint(0,52)])
length-=1
for i in range(length):
varName.append(chars[random.randint(0,62)])
varName=''.join(varName)
return varName def func_info(func):
print '%s() information:'%func.func_name
for name in [x for x in dir(func) if x.startswith('func_')]:
print '%s.%s = %r'%(func.func_name,name,
eval('%s.%s'%(func.func_name,name)))
for name in [x for x in dir(func.func_code) if x.startswith('co_')]:
print '%s.func_code.%s = %r'%(func.func_name,name,
eval('%s.func_code.%s'%(func.func_name,name)))
#输出GetRandName()函数的信息
func_info(GetRandName)
print '-'*80
#输出decorator()函数的信息
func_info(decorator)
print '-'*80
#将GetRandName函数用装饰器先装饰一下
GetRandName=decorator(True)(GetRandName)
#装饰后GetRandName变成__decorator()函数
print 'GetRandName=%r'%GetRandName
#输出此时的GetRandName即__decorator()函数的信息
print '%s() information:'%GetRandName.func_name
for name in [x for x in dir(GetRandName) if x.startswith('func_')]:
print '%s.%s = %r'%(GetRandName.func_name,name,
eval('GetRandName.%s'%name))
for name in [x for x in dir(GetRandName.func_code) if x.startswith('co_')]:
print '%s.func_code.%s = %r'%(GetRandName.func_name,name,
eval('GetRandName.func_code.%s'%name))

运行结果:

 Python 2.7.8 (default, Jun 30 2014, 16:08:48) [MSC v.1500 64 bit (AMD64)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> ================================ RESTART ================================
>>>
GetRandName() information:
GetRandName.func_closure = None
GetRandName.func_code = <code object GetRandName at 0000000002107F30, file "E:\文档\程序库\Python程序\func_information.py", line 18>
GetRandName.func_defaults = (False,)
GetRandName.func_dict = {}
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 "
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>}
GetRandName.func_name = 'GetRandName'
GetRandName.func_code.co_argcount = 2
GetRandName.func_code.co_cellvars = ()
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'
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, '')
GetRandName.func_code.co_filename = 'E:\\\xce\xc4\xb5\xb5\\\xb3\xcc\xd0\xf2\xbf\xe2\\Python\xb3\xcc\xd0\xf2\\func_information.py'
GetRandName.func_code.co_firstlineno = 18
GetRandName.func_code.co_flags = 67
GetRandName.func_code.co_freevars = ()
GetRandName.func_code.co_lnotab = '\x00\x06\x1b\x01\x06\x01!\x01\r\x01\x13\x01!\x01\x0f\x01'
GetRandName.func_code.co_name = 'GetRandName'
GetRandName.func_code.co_names = ('string', 'letters', 'digits', 'append', 'random', 'randint', 'range', 'join')
GetRandName.func_code.co_nlocals = 5
GetRandName.func_code.co_stacksize = 6
GetRandName.func_code.co_varnames = ('length', 'isVar', 'varName', 'chars', 'i')
--------------------------------------------------------------------------------
decorator() information:
decorator.func_closure = None
decorator.func_code = <code object decorator at 0000000002107AB0, file "E:\文档\程序库\Python程序\func_information.py", line 4>
decorator.func_defaults = (False,)
decorator.func_dict = {}
decorator.func_doc = None
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>}
decorator.func_name = 'decorator'
decorator.func_code.co_argcount = 1
decorator.func_code.co_cellvars = ('printResult',)
decorator.func_code.co_code = '\x87\x00\x00f\x01\x00d\x01\x00\x86\x00\x00}\x01\x00|\x01\x00S'
decorator.func_code.co_consts = (None, <code object _decorator at 0000000002107830, file "E:\文档\程序库\Python程序\func_information.py", line 5>)
decorator.func_code.co_filename = 'E:\\\xce\xc4\xb5\xb5\\\xb3\xcc\xd0\xf2\xbf\xe2\\Python\xb3\xcc\xd0\xf2\\func_information.py'
decorator.func_code.co_firstlineno = 4
decorator.func_code.co_flags = 3
decorator.func_code.co_freevars = ()
decorator.func_code.co_lnotab = '\x00\x01\x0f\x0b'
decorator.func_code.co_name = 'decorator'
decorator.func_code.co_names = ()
decorator.func_code.co_nlocals = 2
decorator.func_code.co_stacksize = 2
decorator.func_code.co_varnames = ('printResult', '_decorator')
--------------------------------------------------------------------------------
GetRandName() was post to _decorator()
GetRandName=<function __decorator at 0x0000000002BDD4A8>
__decorator() information:
__decorator.func_closure = (<cell at 0x0000000002BF18E8: function object at 0x0000000002BE0D68>, <cell at 0x0000000002BF1828: bool object at 0x000000001E284280>)
__decorator.func_code = <code object __decorator at 0000000002124030, file "E:\文档\程序库\Python程序\func_information.py", line 8>
__decorator.func_defaults = None
__decorator.func_dict = {}
__decorator.func_doc = None
__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>}
__decorator.func_name = '__decorator'
__decorator.func_code.co_argcount = 0
__decorator.func_code.co_cellvars = ()
__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"
__decorator.func_code.co_consts = (None, 'Call the function %s() in __decorator().', '#print in __decorator().')
__decorator.func_code.co_filename = 'E:\\\xce\xc4\xb5\xb5\\\xb3\xcc\xd0\xf2\xbf\xe2\\Python\xb3\xcc\xd0\xf2\\func_information.py'
__decorator.func_code.co_firstlineno = 8
__decorator.func_code.co_flags = 31
__decorator.func_code.co_freevars = ('func', 'printResult')
__decorator.func_code.co_lnotab = '\x00\x01\x03\x01\t\x01\x06\x01\x15\x02'
__decorator.func_code.co_name = '__decorator'
__decorator.func_code.co_names = ('func_name',)
__decorator.func_code.co_nlocals = 2
__decorator.func_code.co_stacksize = 3
__decorator.func_code.co_varnames = ('args', 'kw')
>>>

Python函数信息的更多相关文章

  1. Day03 - Python 函数

    1. 函数简介 函数是组织好的,可重复使用的,用来实现单一或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率.Python提供了许多内建函数,比如print():也可以自己创建函数,这 ...

  2. python函数参数的pack与unpack

    python函数参数的pack与unpack 上周在使用django做开发的时候用到了mixin(关于mixin我还要写一个博客专门讨论一下,现在请参见这里),其中又涉及到了一个关于函数参数打包(pa ...

  3. Python 3.X 调用多线程C模块,并在C模块中回调python函数的示例

    由于最近在做一个C++面向Python的API封装项目,因此需要用到C扩展Python的相关知识.在此进行简要的总结. 此篇示例分为三部分.第一部分展示了如何用C在Windows中进行多线程编程:第二 ...

  4. python——函数

    python--函数 1.介绍: 在过去的十年间,大家广为熟知的编程方法无非两种:面向对象和面向过程,其实,无论哪种,都是一种编程的规范或者是如何编程的方法论.而如今,一种更为古老的编程方式:函数式编 ...

  5. 【转】Python函数默认参数陷阱

    [转]Python函数默认参数陷阱 阅读目录 可变对象与不可变对象 函数默认参数陷阱 默认参数原理 避免 修饰器方法 扩展 参考 请看如下一段程序: def extend_list(v, li=[]) ...

  6. Python函数声明以及与其他编程语言数据类型的比较

    1.函数声明 与其它大多数语言一样 Python 有函数,但是它没有像 C++ 一样的独立的头文件:或者像 Pascal 一样的分离的  interface / implementation 段.在需 ...

  7. Python面试题目之Python函数默认参数陷阱

    请看如下一段程序: def extend_list(v, li=[]): li.append(v) return li list1 = extend_list(10) list2 = extend_l ...

  8. python -- 函数进阶

    一.函数参数-动态传参       1.形参:         *   在形参位置, 表示此参数为不定参数,接受的是位置参数            并且接收到的位置参数的动态传参都是元组 def fu ...

  9. Python函数属性和PyCodeObject

    函数属性 python中的函数是一种对象,它有属于对象的属性.除此之外,函数还可以自定义自己的属性.注意,属性是和对象相关的,和作用域无关. 自定义属性 自定义函数自己的属性方式很简单.假设函数名称为 ...

随机推荐

  1. js性能优化-事件委托

    js性能优化-事件委托 考虑一个列表,在li的数量非常少的时候,为每一个li添加事件侦听当然不会存在太多性能方面的问题,但是当列表非常的长,长到上百上千甚至上万的时候(当然只是一个解释,实际工作中很少 ...

  2. 基于Spring + Spring MVC + Mybatis + shiro 高性能web构建

    一直想写这篇文章,前段时间 痴迷于JavaScript.NodeJs.AngularJS,做了大量的研究,对前后端交互有了更深层次的认识. 今天抽个时间写这篇文章,我有预感,这将是一篇很详细的文章,详 ...

  3. 日志分析_使用shell完整日志分析案例

    一.需求分析 1. 日志文件每天生成一份(需要将日志文件定时上传至hdfs) 2. 分析日志文件中包含的字段:访问IP,访问时间,访问URL,访问状态,访问流量 3. 现在有"昨日" ...

  4. jquery实现限制textarea输入字数

    ie中可用onpropertychange监听改变事件 火狐和谷歌可用oninput监听改变事件 综合: //使系统中class='text-length'的输入框只能输入200字符(主要用于text ...

  5. 重学ps_1

    1,选取 打开图片->点击选取工具->ctrl+c->ctrl+n->ctrl+v 2,去除图片背景 打开你要去除背景的图片->在图层面板中->双击图层把图层改为0 ...

  6. PHP写在线视频直播技术详解

    2016年7月22日 22:26:45 交流QQ:903464207 本文会不断更新 废话一句,如果你要做高性能服务器服务,请去读底层的东西 http tcp/ip socket 了解基础协议,你对如 ...

  7. 一道无限级分类题的 PHP 实现

    今天有网友出了道题: 给出如下的父子结构(你可以用你所用语言的类似结构来描述,第一列是父,第二列是子),将其梳理成类似如图的层次父子结构. origin = [('A112', 'A1122'), ( ...

  8. win7与virtualbox中centos文件共享

    1.首先在Windows下创建一个文件夹,用于存放共享的文件,例如 E:\share 2.将该文件夹设置为共享文件夹. 右击文件夹,选择共享->特定用户 选择Everyone->添加-&g ...

  9. https://blog.helong.info/blog/2015/03/13/jump_consistent_hash/

    转载请说明出处:http://blog.csdn.net/cywosp/article/details/23397179     一致性哈希算法在1997年由麻省理工学院提出的一种分布式哈希(DHT) ...

  10. Arduino.h

    #ifndef Arduino_h #define Arduino_h #include <stdlib.h> #include <stdbool.h> #include &l ...