赞
踩
本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie
1.Python虚拟机在执行函数调用时会动态地创建新的 PyFrameObject对象,
这些PyFrameObject对象之间会形成PyFrameObject对象链,模拟x86平台上运行时栈
2.PyFuctionObject对象
- typedef struct {
- PyObject_HEAD
- PyObject *func_code; //对应函数编译后的PyCodeObject对象
- PyObject *func_globals; //函数运行时的global空间
- PyObject *func_defaults; //默认参数(tuple或NULL)
- PyObject *func_closure; //NULL or a tuple of cell objects,用于实现closure
- PyObject *func_doc; //函数的文档(PyStringObject)
- PyObject *func_name; //函数名称,函数的__name__属性,(PyStringObject)
- PyObject *func_dict; //函数的__dict__属性(PyDictObject或NULL)
- PyObject *func_weakreflist;
- PyObject *func_module; //函数的__module__,可以是任何对象
- } PyFunctionObject;
- def f():
- #LOAD_CONST 0
- #MAKE_FUNCTION 0
- #STORE_NAME 0
- print "Function"
- #LOAD_CONST 1
- #PRINT_ITEM
- #PRINT_NEWLINE
- #LOAD_CONST
- #RETURN_VALUE
- f()
- #LOAD_NAME 0
- #CALL_FUNCTION 0
- #POP_TOP
- #LOAD_CONST 1
- #RETURN_VALUE
def f()创建了函数对象,如图11-6所示
call_function函数调用
- static PyObject *
- call_function(PyObject ***pp_stack, int oparg
- #ifdef WITH_TSC
- , uint64* pintr0, uint64* pintr1
- #endif
- )
- {
- //[1]:处理函数参数信息
- int na = oparg & 0xff; //位置参数、扩展位置参数个数
- int nk = (oparg>>8) & 0xff; //键参数、扩展键参数个数
- int n = na + 2 * nk; //总共的参数个数 nk*2是因为(键,值)对中键和值各占一个位置
- //[2]:获得PyFunctionObject对象
- PyObject **pfunc = (*pp_stack) - n - 1;
- PyObject *func = *pfunc;
- PyObject *x, *w;
-
-
- if (PyCFunction_Check(func) && nk == 0) {
- //...
-
- } else {
- if (PyMethod_Check(func) && PyMethod_GET_SELF(func) != NULL) {
-
- } else
- //[3]:对PyFunctionObject对象进行调用
- if (PyFunction_Check(func))
- x = fast_function(func, pp_stack, n, na, nk);
- else
- x = do_call(func, pp_stack, na, nk);
- //...
- }
- //...
- return x;
- }
- static PyObject *
- fast_function(PyObject *func, PyObject ***pp_stack, int n, int na, int nk)
- {
- PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func);
- PyObject *globals = PyFunction_GET_GLOBALS(func);
- PyObject *argdefs = PyFunction_GET_DEFAULTS(func);
- PyObject **d = NULL;
- int nd = 0;
-
-
- //...
- //[1]:一般函数的快速通道
- if (argdefs == NULL && co->co_argcount == n && nk==0 &&
- co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) {
- PyFrameObject *f;
- PyObject *retval = NULL;
- PyThreadState *tstate = PyThreadState_GET();
- PyObject **fastlocals, **stack;
- int i;
-
-
- f = PyFrame_New(tstate, co, globals, NULL);
- //...
- retval = PyEval_EvalFrameEx(f,0);
- //...
- return retval;
- }
- if (argdefs != NULL) {
- d = &PyTuple_GET_ITEM(argdefs, 0);
- nd = Py_SIZE(argdefs);
- }
- return PyEval_EvalCodeEx(co, globals,
- (PyObject *)NULL, (*pp_stack)-n, na,
- (*pp_stack)-2*nk, nk, d, nd,
- PyFunction_GET_CLOSURE(func));
- }
- def fun(a, b):
- pass
- fun(1, b = 2)
- def f(name, age):
- #LOAD_CONST 0
- #MAKE_FUNCTION 0
- #STORE_NAME 0
- age += 5
- #LOAD_FAST 1
- #LOAD_CONST 5
- #INPLACE_ADD
- #STORE_FAST 1
- print "[", name, ",", age, "]"
- #LOAD_CONST 2
- #PRINT_ITEM
- #LOAD_FAST 0
- #PRINT_ITEM
- #LOAD_CONST 3
- #PRINT_ITEM
- #LOAD_FAST 1
- #PRINT_ITEM
- #LOAD_CONST 4
- #PRINT_ITEM
- #PRINT_NEWLINE
- #LOAD_CONST 0
- #RETURN_VALUE
- age = 5;
- print age
- f("Robert", age)
- #LOAD_NAME 0
- #LOAD_CONST 2
- #LOAD_NAME 1
- #CALL_FUNCTION 2
- #POP_TOP
- print age
call_function --> fast_function
- def f(a = 1, b = 2):
- #LOAD_CONST 0
- #LOAD_CONST 1
- #LOAD_CONST 2
- #MAKE_FUNCTION 2
- #STORE_NAME 0
- print a + b
- #LOAD_FAST 0
- #LOAD_FAST 1
- #BINARY_ADD
- #PRINT_ITEM
- #PRINT_NEWLINE
- #LOAD_CONST 0
- #RETURN_VALUE
- f()
- #LOAD_NAME 0
- #CALL_FUNCTION 0
- #POP_TOP
- f(b=3)
- #LOAD_NAME 0
- #LOAD_CONST 3
- #LOAD_CONST 4
- #CALL_FUNCTION 256
- #POP_TOP
- #LOAD_CONST 5
- #RETURN_VALUE
- PyObject *
- PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
- PyObject **args, int argcount, PyObject **kws, int kwcount,
- PyObject **defs, int defcount, PyObject *closure)
- {
- register PyFrameObject *f;
- register PyObject *retval = NULL;
- register PyObject **fastlocals, **freevars;
- PyThreadState *tstate = PyThreadState_GET();
- PyObject *x, *u;
- //[1]:创建PyFrameObject对象
- f = PyFrame_New(tstate, co, globals, locals);
-
- fastlocals = f->f_localsplus;
- freevars = f->f_localsplus + co->co_nlocals;
-
- //[a]:遍历键参数,确定函数的def语句中是否出现了键参数的名字
- for (i = 0; i < kwcount; i++) {
- PyObject *keyword = kws[2*i];
- PyObject *value = kws[2*i + 1];
- int j;
- //[b]:在函数的变量名表中寻找keyword
- //...
- for (j = 0; j < co->co_argcount; j++) {
- PyObject *nm = co_varnames[j];
- int cmp = PyObject_RichCompareBool(
- keyword, nm, Py_EQ);
- if (cmp > 0)
- goto kw_found;
- else if (cmp < 0)
- goto fail;
- }
- if (kwdict == NULL) {
- PyObject *kwd_str = kwd_as_string(keyword);
- if (kwd_str) {
- PyErr_Format(PyExc_TypeError,
- "%.200s() got an unexpected "
- "keyword argument '%.400s'",
- PyString_AsString(co->co_name),
- PyString_AsString(kwd_str));
- Py_DECREF(kwd_str);
- }
- goto fail;
- }
- PyDict_SetItem(kwdict, keyword, value);
- continue;
- kw_found:
- if (GETLOCAL(j) != NULL) {
- goto fail;
- }
- Py_INCREF(value);
- SETLOCAL(j, value);
- }
-
- if (co->co_argcount > 0 ||
- co->co_flags & (CO_VARARGS | CO_VARKEYWORDS)) {
- int i;
- int n = argcount;
- PyObject *kwdict = NULL;
- //n为CALL_FUNCTION的参数指示的传入的位置参数个数,即na,这里为0
-
- //...
-
- //[2]:判断是否使用参数的默认值
- if (argcount < co->co_argcount) {
- //m 一般位置参数的个数
- int m = co->co_argcount - defcount;
- //[3]:函数调用者必须传递一般位置参数的参数值
- for (i = argcount; i < m; i++) {
- if (GETLOCAL(i) == NULL) {
- goto fail;
- }
- }
- //[4]:n > m意味着调用者希望替换一些默认位置参数的默认值
- if (n > m)
- i = n - m;
- else
- i = 0;
- //[5]:设置默认位置参数的默认值
- for (; i < defcount; i++) {
- if (GETLOCAL(m+i) == NULL) {
- PyObject *def = defs[i];
- Py_INCREF(def);
- SETLOCAL(m+i, def);
- }
- }
- }
- }
-
- retval = PyEval_EvalFrameEx(f,0);
- return retval;
- }
- PyObject *
- PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
- PyObject **args, int argcount, PyObject **kws, int kwcount,
- PyObject **defs, int defcount, PyObject *closure)
- {
- register PyFrameObject *f;
- register PyObject **fastlocals, **freevars;
- PyThreadState *tstate = PyThreadState_GET();
- PyObject *x, *u;
- //创建PyFrameObject对象
- f = PyFrame_New(tstate, co, globals, locals);
- fastlocals = f->localsplus;
- freevars = f->f_localsplus + f->f_nlocals;
- //[1]:判断是否需要处理扩展位置参数或扩展键参数
- if(co->co_argcount > 0 || co->co_flags & (CO_VARARGS | CO_VARKEYWORDS)){
- int i;
- int n = argcount;
-
- if(argcount > co->co_argcount ){
- n = co->co_argcount;
- }
- //[2]:设置位置参数的参数值
- for(i = 0; i < n; i++){
- x = args[i];
- SETLOCAL(i, x);
- }
- //[3]:处理扩展位置参数
- if(co->co_flags & CO_VARARGS){
- //[4]:将PyTupleObject对象放入到f_localsplus中
- u = PyTuple_New(argcount - n );
- SETLOCAL(co->co_argcount, u);
- //[5]:将扩展位置参数放入到PyTupleObject中
- for( i = n; i < argcount; i++){
- x = args[i];
- PyTuple_SET_ITEM(u, i - n, x);
- }
- }
- }
-
- }
- PyObject *
- PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
- PyObject **args, int argcount, PyObject **kws, int kwcount,
- PyObject **defs, int defcount, PyObject *closure)
- {
- //...
- if(co->co_flags > 0 || co->co_flags & (CO_VARARGS | CO_VARKEYWORDS)){
- int i;
- int n = argcount;
- PyObject *kwdict = NULL;
- //...
- //[1]:创建PyDictObject对象,并将其放到f_localsplus中
- if(co->co_flags & CO_VARKEYWORDS){
- kwdict = PyDict_New();
- i = co->co_argcount;
- //[2]:PyDictObject对象必须在PyTupleObject之后
- if(co->co_flags & CO_VARARGS)
- i++;
- SETLOCAL(i, kwdict);
- }
- //遍历键参数,确定函数的def语句中是否出现了键参数的名字
- for(i = 0; i < kwcount; i++){
- PyObject *keyword = kws[2 * i];
- PyObject *value = kws[2 * i + 1];
- int j;
- //在函数的变量名表中寻找keyword
- for(j = 0; j < co->co_argcount; j++){
- PyObject *nm = PyTuple_GET_ITEM(co->co_varnames, j);
- int cmp = PyObject_RichCompareBool(keyword, nm, Py_EQ);
- if(cmp > 0)//在co_varnames中找到keyword
- break;
- else if (cmp < 0)
- goto fail;
- }
-
- //[3]:keyword没有在变量名对象表中出现
- if(j >= co->co_argcount){
- PyDict_SetItem(kwdict, keyword, value);
- }
- //keyword在变量名对象表中出现
- else{
- SETLOCAL(j, value);
- }
-
- }
- }
- }
- def get_func():
- LOAD_CONST 0
- MAKE_FUNCTION
- STORE_NAME 0
- value = "inner"
- LOAD_CONST 1
- STORE_DEREF 0
- def inner_func():
- LOAD_CLOSUER 0
- BUILD_TUPLE
- LOAD_CONST 2
- MAKE_CLOSURE 0
- STORE_FAST 0
- print value
- LOAD_DEREF 0
- PRINT_ITEM
- PRINT_NEWLINE
- LOAD_CONST 0
- RETURN_VALUE
- return inner_func
- LOAD_FAST 0
- RETURN_VALUE
- show_value = get_func()
- LOAD_NAME 0
- CALL_FUNCTION 0
- STORE_NAME 1
- show_value()
- LOAD_NAME 1
- CALL_FUNCTION 0
- POP_TOP
- LOAD_CONST
- RETURN_VALUE
- def should_say(fn):
- def say(*args):
- print 'say something ...'
- fn(*args)
- return say
- @should_say
- def func():
- print 'in func'
- #...
- def func():
- print 'in func'
- func = should_say(func)
- func()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。