在Python内核看来,任何一个代码作用域都会对应一个PyCodeObject。
Py3K的PyCodeObject定义在code.h中,位于/branches/py3k/Include,如下所示
/* Bytecode object */
typedef struct {
PyObject_HEAD
int co_argcount; /* #arguments, except *args */
int co_kwonlyargcount; /* #keyword only arguments */
int co_nlocals; /* #local variables */
int co_stacksize; /* #entries needed for evaluation stack */
int co_flags; /* CO_..., see below */
PyObject *co_code; /* instruction opcodes */
PyObject *co_consts; /* list (constants used) */
PyObject *co_names; /* list of strings (names used) */
PyObject *co_varnames; /* tuple of strings (local variable names) */
PyObject *co_freevars; /* tuple of strings (free variable names) */
PyObject *co_cellvars; /* tuple of strings (cell variable names) */
/* The rest doesn't count for hash or comparisons */
PyObject *co_filename; /* unicode (where it was loaded from) */
PyObject *co_name; /* unicode (name, for reference) */
int co_firstlineno; /* first source line number */
PyObject *co_lnotab; /* string (encoding addr<->lineno mapping) */
void *co_zombieframe; /* for optimization only (see frameobject.c) */
} PyCodeObject;
1. argcount vs. kwonlyargcount
[http://www.python.org/dev/peps/pep-3102]
argcount
在调用时必须出现的参数的个数,不包含可变参数
kwonlyargcount
在调用时必须出现、形式为"key=value"、出现在可变参数之后的参数的个数
举例:
-------------------------------------------------------
def weirdo(a,b,*c,d):
pass
print(weirdo.__code__.co_argcount)
print(weirdo.__code__.co_kwonlyargcount)
-------------------------------------------------------
结果:
-------------------------------------------------------
2
1
-------------------------------------------------------
2. co_nlocals
所有参数的个数,包括argcount+kwonlyargcount,还有可变参数的个数
举例:
-------------------------------------------------------
>>> def weirdo(a,b,*c,d):pass
...
>>> weirdo.__code__.co_nlocals
4
-------------------------------------------------------
3. co_varnames vs. co_freevars vs. co_cellvars
co_varnames
在本代码段中被赋值、没有被内层代码段引用的变量
co_freevars
在本代码段中被引用、在外层代码被赋值的变量
co_cellvars
在本代码段中被赋值、且被内层代码段引用的变量
[记忆]
free自由,cell牢房
cell变量是被内层代码段约束的变量
举例:
-------------------------------------------------------
def fa():
a = 1
b = 2
def fb():
c = a
d = 3
print(fb.__code__.co_varnames)
print(fb.__code__.co_freevars)
print(fb.__code__.co_cellvars)
fa()
print(fa.__code__.co_varnames)
print(fa.__code__.co_freevars)
print(fa.__code__.co_cellvars)
-------------------------------------------------------
结果:
-------------------------------------------------------
('c','d')
('a',)
()
('b','fb')
()
('a',)
-------------------------------------------------------
4. co_filename vs. co_name
前者代表代码段所在文件的全名对应的对象,后者代表本代码段的名字对应的对象。
如果是在Python Shell中定义的代码段,因为代码段是用户用键盘一字一字敲入,所在文件的名字是<stdin>,
举例:
------------------------------------------------
>>> def fa():pass
...
>>> fa.__code__.co_filename
'<stdin>'
------------------------------------------------