定义一个简单的Python函数

dir(f)可以看到函数的几个主要属性 ‘func_closure’, ‘func_code’, ‘func_defaults’, ‘func_dict’, ‘func_doc’, ‘func_globals’, ‘func_name’。在funcobject.c中对PyFunction_Type的定义中可以看到这些属性的来源:

static PyMemberDef func_memberlist[] = {
    {"func_closure", T_OBJECT, OFF(func_closure), RESTRICTED|READONLY},
    {"func_doc",     T_OBJECT, OFF(func_doc), WRITE_RESTRICTED},
    {"__doc__",      T_OBJECT, OFF(func_doc), WRITE_RESTRICTED},
    {"func_globals", T_OBJECT, OFF(func_globals), RESTRICTED|READONLY},
    {"__module__",   T_OBJECT, OFF(func_module), WRITE_RESTRICTED},
    {NULL}  /* Sentinel */
};
static PyGetSetDef func_getsetlist[] = {
    {"func_code", (getter)func_get_code, (setter)func_set_code},
    {"func_defaults", (getter)func_get_defaults, (setter)func_set_defaults},
    {"func_dict", (getter)func_get_dict, (setter)func_set_dict},
    {"__dict__", (getter)func_get_dict, (setter)func_set_dict},
    {"func_name", (getter)func_get_name, (setter)func_set_name},
    {"__name__", (getter)func_get_name, (setter)func_set_name},
    {NULL} /* Sentinel */
};

f.func_defaults记录函数的默认值,这个例子中就是一个tuple(10,16)

f.func_code是一个code对象,对应于源码中的PyCodeObject。除了《Python源码剖析》中提到的几个属性外,有三个tuple记录了不同类型的变量,co_varnames, co_freevars和co_cellvars,分别对应local variables, free variables和cell variables。

free variables指enclosing scope中的变量,cell variables则是指会被多个scope访问的变量。

def foo():
    a = 5
    def bar():
        return a
    print "cellvars:", bar.func_code.co_cellvars
    print "freevars:", bar.func_code.co_freevars
    return bar

g = foo()
print foo.func_code.co_freevars
print foo.func_code.co_cellvars

最后的结果显示bar的cellvars为空,freevars为(‘a’, 0);foo的cellvars为(‘a’, 0),freevars为空。